Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
235 commits
Select commit Hold shift + click to select a range
07d648d
chore(release): 1.0.4, first public release
xiaodoudou Dec 13, 2022
27667ea
chore(release): 1.0.15, MongoDB with client certificates and a cleare…
xiaodoudou Jan 3, 2023
7a09fff
chore(release): 1.0.48, the system log page and multiple selection
xiaodoudou Jan 12, 2023
b43e921
chore(release): 1.1.6, authentication
xiaodoudou Feb 16, 2023
c4e3402
chore(release): 1.1.16, sessions, WebSockets and replication fixes
xiaodoudou Aug 4, 2023
0604ac5
chore(release): 1.1.22, the spreadsheet import and dependency updates
xiaodoudou Jun 24, 2024
7bf085b
chore(release): 1.1.25, MongoDB queries are sanitised
xiaodoudou Jul 14, 2025
3d5e883
chore(release): 2.1.99, Vue 3, Vuetify 3 and Vite
xiaodoudou Aug 12, 2025
f543062
chore(release): 2.2.9, smart cropping and SVG icons
xiaodoudou Nov 24, 2025
df3672e
chore(release): 2.3.9, hints, sorting by update and database closing
xiaodoudou Jan 4, 2026
7f03783
chore(release): 2.4.9, import cache, file limits and the dark mode sw…
xiaodoudou Jan 15, 2026
58c75aa
chore(release): 2.5.9, code fields, unit tests and login fixes
xiaodoudou Feb 2, 2026
11082c2
chore(release): 2.6.1, image metadata, OSS storage and the PostgreSQL…
xiaodoudou Mar 23, 2026
bfe6e39
feat(admin): redesign the admin, add tests and CI, and harden the bac…
xiaodoudou Sep 30, 2026
f0140ad
chore(admin): polish the admin, add the recommended production config…
xiaodoudou Sep 30, 2026
559fcbc
build(deps): upgrade every dependency that fits, with the fixes they …
xiaodoudou Sep 30, 2026
514d2ff
test(admin): add frontend component tests and fix the bugs they found
xiaodoudou Oct 1, 2026
c2f2d60
docs: refactor the docs to one source of truth per topic, checked aga…
xiaodoudou Oct 1, 2026
4b30452
fix: fix every bug from the documentation review and test every compo…
xiaodoudou Oct 1, 2026
86f256a
feat(logs): colorize the console logs, also on the System log page
xiaodoudou Oct 1, 2026
02721a4
feat(security)!: turn every protection on by default, and rewrite the…
xiaodoudou Oct 1, 2026
41c3a31
ci: remove the CI warnings and fix the two bugs they hid
xiaodoudou Oct 1, 2026
e5e9034
feat(storage): add LevelDB and SQLite stores beside the JSON file, Mo…
xiaodoudou Oct 1, 2026
48ec8d4
chore(release): 3.0.0, under the GNU GPL version 3 only
xiaodoudou Oct 1, 2026
0cc4e60
fix(fields): set autocomplete to nope so Brave stops offering an emai…
xiaodoudou Oct 1, 2026
9714051
feat(admin): flat redesign of the object and list editor
xiaodoudou Oct 1, 2026
8507fc0
feat(admin): remove the Cms Config page and list Syslog in the CMS menu
xiaodoudou Oct 1, 2026
55e2485
fix(logs): keep a very long log from filling the disk, the memory or …
xiaodoudou Oct 1, 2026
7924dc8
feat(admin): softer login page that follows the system theme
xiaodoudou Oct 1, 2026
19a4eb9
fix(admin): show live network traffic in the System card, not the tot…
xiaodoudou Oct 1, 2026
cd91849
fix(admin): keep Tab inside the omnibar switcher
xiaodoudou Oct 1, 2026
96557bb
fix(admin): remove the colour fade on record rows and match the syste…
xiaodoudou Oct 1, 2026
9067b28
fix(admin): add or remove a record with a click on its row when choos…
xiaodoudou Oct 1, 2026
dc0f6dc
feat(admin): follow the user's theme, language and tab title, and dro…
xiaodoudou Oct 1, 2026
71c0041
feat: rebrand node-cms as Embed CMS with a new logo
xiaodoudou Oct 1, 2026
a042c21
docs: review the docs against the code and the changes since 3.0.0
xiaodoudou Oct 1, 2026
bfafd78
build: load rollup-plugin-visualizer 7 only for ANALYZE=1 npm run build
xiaodoudou Oct 1, 2026
d83aece
build(deps): chai 6
xiaodoudou Oct 1, 2026
8667ad0
build(deps): vue-virtual-scroller 3
xiaodoudou Oct 1, 2026
77e346b
build(deps): @vuepic/vue-datepicker 14 and date-fns 4 as a direct dep…
xiaodoudou Oct 1, 2026
ec6882b
fix(auth): make the no-login mode work and sign what it writes
xiaodoudou Oct 1, 2026
c7b6f69
chore(release): 3.0.1, the first version on npm
xiaodoudou Oct 1, 2026
ee4d969
ci(release): run the tests, publish to npm and create the GitHub rele…
xiaodoudou Oct 1, 2026
0fcd24d
build(deps): fetch vue3-shortkey as a tarball, as a dev dependency
xiaodoudou Oct 1, 2026
b164123
chore(release): 3.0.2
xiaodoudou Oct 1, 2026
d757513
build: update to Vuetify 4 and extend the build tooling
xiaodoudou Oct 2, 2026
c311f03
feat(server): add the sqlite store, the record author and the rights …
xiaodoudou Oct 2, 2026
18d7ad1
feat(admin): add Vuetify 4, SCSS design tokens, the plugin UI kit and…
xiaodoudou Oct 2, 2026
f5accb6
test: add frontend, OSS and driver contract tests, and checks for the…
xiaodoudou Oct 2, 2026
d47455d
test(bench): benchmark the whole CMS on all five storage engines
xiaodoudou Oct 2, 2026
b8590e3
docs: reorganise the docs by purpose
xiaodoudou Oct 2, 2026
5026df6
docs: update the screenshots
xiaodoudou Oct 2, 2026
b92f856
chore(release): 3.0.3
xiaodoudou Oct 2, 2026
4c4caa2
feat(admin): deeper indigo primary, edge-to-edge menus and a lock on …
xiaodoudou Oct 3, 2026
142ace2
feat(groups): make the Plugins field a drop-down of the plugin pages
xiaodoudou Oct 3, 2026
05aab0a
feat(resources): add layout examples to the catalogue, tiles in a gri…
xiaodoudou Oct 3, 2026
9294372
feat(admin): put the Jump to menu on every form, with the blocks and …
xiaodoudou Oct 3, 2026
fd886aa
feat(sync): choose the resources to sync in the Sync settings
xiaodoudou Oct 3, 2026
2cf771c
feat(sync): push or pull all resources from the admin, code, command …
xiaodoudou Oct 3, 2026
293beb0
feat(sync): sync the relations and files inside paragraph blocks
xiaodoudou Oct 3, 2026
45d29b6
feat(sync): follow record ids written in texts and JSON to the same r…
xiaodoudou Oct 3, 2026
498176b
fix(attachments): build the field path pattern without the double esc…
xiaodoudou Oct 3, 2026
46a0262
feat(api): resolve relations named after a resource, inside paragraph…
xiaodoudou Oct 3, 2026
5b798f4
perf(rest): compile the attachment field patterns once per request
xiaodoudou Oct 3, 2026
00471b1
feat(api): add bulk() to run many writes with one wait for the disk
xiaodoudou Oct 3, 2026
502d57e
perf(sync): find the records of each side by unique key and wait for …
xiaodoudou Oct 3, 2026
1662a02
refactor(import): use the logger instead of console.log
xiaodoudou Oct 3, 2026
52bd362
perf: check unique values against an index in memory
xiaodoudou Oct 3, 2026
b7c0d26
refactor(driver): use a Node EventEmitter for the context and pipelin…
xiaodoudou Oct 3, 2026
f6809eb
style: enforce prefer-const and eqeqeq on the backend
xiaodoudou Oct 3, 2026
73dc9ed
test: let the two tests that load the whole package wait as long as a…
xiaodoudou Oct 3, 2026
a98ff6e
fix(fields): hand a dropped file to the file field of its paragraph b…
xiaodoudou Oct 3, 2026
44195d7
refactor(admin): drop $forceUpdate, declare component events, enforce…
xiaodoudou Oct 3, 2026
da5f02f
docs: add a changelog from 3.0.0 and the release steps that keep it
xiaodoudou Oct 3, 2026
eeeb9cc
refactor(admin): replace vue3-shortkey with our own v-shortkey directive
xiaodoudou Oct 3, 2026
e43fb91
docs(backend): add a typed doc comment to every function and rename m…
xiaodoudou Oct 3, 2026
4d221fc
docs(admin): add a typed doc comment to every function and rename mis…
xiaodoudou Oct 3, 2026
6ee45ed
fix(admin): list the Replicator page from disableReplication in /admi…
xiaodoudou Oct 4, 2026
49888ff
fix(admin): resend a saved image or file with its order when it moves
xiaodoudou Oct 4, 2026
409fb09
fix(fields): make the label before a field a real label pointing at i…
xiaodoudou Oct 4, 2026
ed150b2
feat(fields): add a Today button to date fields
xiaodoudou Oct 4, 2026
d885c7e
fix(admin): drag with a mouse at once and keep lists from sharing a d…
xiaodoudou Oct 4, 2026
7817f4f
fix(admin): select no text while dragging, show a grab cursor and lea…
xiaodoudou Oct 4, 2026
8095e01
feat(admin): start a drag from a grip icon on blocks, images and files
xiaodoudou Oct 4, 2026
7f3f165
fix(admin): show the grip beside the file name and only with two item…
xiaodoudou Oct 4, 2026
25cc125
fix(admin): make the upload area a field like the others
xiaodoudou Oct 4, 2026
300225f
fix(admin): keep the forms of moved, dragged or removed blocks
xiaodoudou Oct 4, 2026
ba57bdd
feat(api): cut an image by a crop recipe kept with it
xiaodoudou Oct 4, 2026
68bcb04
feat(fields): add the cropimage field with a crop tool
xiaodoudou Oct 4, 2026
2c76450
fix(fields): open the small picture of an unsaved crop without fetchi…
xiaodoudou Oct 4, 2026
e736e96
docs(fields): say what the crop image form shows and what a click does
xiaodoudou Oct 4, 2026
15a88f6
feat(api): add the image map of a picture
xiaodoudou Oct 4, 2026
e6448a8
feat(api): let an image map area hold a typed value
xiaodoudou Oct 4, 2026
43dd295
feat(fields): add the imagemap field
xiaodoudou Oct 4, 2026
31b7dcd
fix(fields): fill the stage of the image map with the picture
xiaodoudou Oct 4, 2026
ef0057a
docs(fields): add screenshots of the crop image and image map fields
xiaodoudou Oct 4, 2026
6b04b24
feat(fields): add the rating field
xiaodoudou Oct 4, 2026
e4a8cf6
feat(fields): add the duration field
xiaodoudou Oct 4, 2026
cee2575
fix(fields): do not show the required message of a duration before it…
xiaodoudou Oct 4, 2026
fe103a7
feat(fields): add the money field
xiaodoudou Oct 4, 2026
9460c7a
feat(fields): add the phone field
xiaodoudou Oct 4, 2026
896d6cc
feat(fields): type a duration in one box the way people write it
xiaodoudou Oct 4, 2026
e36acdc
feat(fields): keep the template in the duration box while typing
xiaodoudou Oct 4, 2026
d208b7b
feat(fields): list the records of several resources in one select wit…
xiaodoudou Oct 4, 2026
89b5a10
feat(fields): add input masks, a template that stays in the box while…
xiaodoudou Oct 4, 2026
1c4d568
docs(fields): add screenshots of the rating, duration, money, phone a…
xiaodoudou Oct 4, 2026
b915a83
test(fields): test the escapes of a mask template
xiaodoudou Oct 4, 2026
8745d4f
test(admin): print a handful of lines instead of about 3900 Vue warnings
xiaodoudou Oct 4, 2026
f204bef
fix(admin): write ID copied in the toast after copying a record id
xiaodoudou Oct 4, 2026
60c14b0
fix(admin): change the theme at once and keep it on the server in the…
xiaodoudou Oct 4, 2026
9c5a3d6
test(admin): catch the console errors the tests expect so a run print…
xiaodoudou Oct 4, 2026
f5c8a90
feat(logs): show the real console output of the CMS on the log page o…
xiaodoudou Oct 4, 2026
288f061
feat(fields): add the markdown field
xiaodoudou Oct 4, 2026
948234c
feat(fields): add the daterange field
xiaodoudou Oct 4, 2026
342b4cd
feat(fields): add the geopoint field
xiaodoudou Oct 5, 2026
785b165
fix(fields): label the longitude box of the geopoint field
xiaodoudou Oct 5, 2026
0653f8c
feat(fields): add the radio and segmented fields
xiaodoudou Oct 5, 2026
6f8066f
test(admin): run a failing frontend test again, twice, before it coun…
xiaodoudou Oct 5, 2026
02401b3
fix(fields): give the geopoint map search box a real label
xiaodoudou Oct 5, 2026
e765c00
fix(admin): open the calendars of date fields over the page on a phone
xiaodoudou Oct 5, 2026
f2866b4
fix(admin): make every button 44px on touch screens
xiaodoudou Oct 5, 2026
bdd292d
fix(admin): give the record editor more room on a phone
xiaodoudou Oct 5, 2026
0d0825f
fix(admin): stack form layout lines in a narrow editor
xiaodoudou Oct 5, 2026
7a41110
feat(i18n): name ninety languages and show a language by its code whe…
xiaodoudou Oct 5, 2026
2bafd16
feat(i18n): put the translation files of a project over the words of …
xiaodoudou Oct 5, 2026
6f2c7e7
fix(admin): put the block type and the Add button on one line on a phone
xiaodoudou Oct 5, 2026
5c38cfd
fix(admin): make image and file previews take the whole line in a nar…
xiaodoudou Oct 5, 2026
a3c6539
fix(admin): use the phone layout for a phone on its side
xiaodoudou Oct 5, 2026
2f3557d
fix(admin): start a drag by touch as soon as the finger moves 3px fro…
xiaodoudou Oct 5, 2026
0400f56
fix(admin): centre the title and grip in the block bar on a touch screen
xiaodoudou Oct 5, 2026
7b1d62a
fix(admin): hide the breadcrumb on a phone with a class instead of a …
xiaodoudou Oct 5, 2026
91cbe88
fix(admin): round all corners of a block folded to its bar
xiaodoudou Oct 5, 2026
bdd76ba
perf(admin): hide folded blocks with content-visibility while a block…
xiaodoudou Oct 5, 2026
3c09cd4
feat(admin): show the language of a record as one button on a phone
xiaodoudou Oct 5, 2026
3b3d398
fix(admin): keep the editor bar of a new record on one line on a phone
xiaodoudou Oct 5, 2026
9c0bd2a
fix(admin): mobile review, round two
xiaodoudou Oct 5, 2026
0099c37
fix(admin): show on the language button how many other languages need…
xiaodoudou Oct 5, 2026
5ea49f9
fix(admin): centre the pills of the editor bar on one line
xiaodoudou Oct 5, 2026
04f5f5d
fix(fields): warn once about a slug without options.valueFrom
xiaodoudou Oct 5, 2026
d49d2da
fix(resources): give the Slug of the Languages resource a source and …
xiaodoudou Oct 5, 2026
ea32b7d
feat(fields): groups that close, start closed and have a layout of th…
xiaodoudou Oct 5, 2026
3e58711
fix(admin): align the Jump to field search box with the rows
xiaodoudou Oct 5, 2026
c559721
fix(admin): make the Jump to field search box the first line of the menu
xiaodoudou Oct 5, 2026
488e894
fix(admin): move the magnifier of the Jump to field search box off th…
xiaodoudou Oct 5, 2026
3a20b63
fix(admin): make the Jump to field search box 44px tall on a touch sc…
xiaodoudou Oct 5, 2026
d478a4a
docs: say the Jump to field search box is 44px tall on a touch screen
xiaodoudou Oct 5, 2026
4a140d9
fix(admin): show only the list in Jump to field on a phone or a touch…
xiaodoudou Oct 5, 2026
711a91f
feat: add the PageHelper for the pages of a public site
xiaodoudou Oct 6, 2026
63032dc
feat: add the ContentLoader and the cms-load command
xiaodoudou Oct 6, 2026
dfcf366
docs(examples): add the magazine, a second example site built with no…
xiaodoudou Oct 6, 2026
f0c9ed9
chore: give main one commit per release and keep the work on dev
xiaodoudou Oct 6, 2026
8a26239
chore: merge the releases up to 3.0.3 from main
xiaodoudou Oct 6, 2026
92a9c2a
docs: say which page to read for each question in the docs map
xiaodoudou Oct 6, 2026
9a13665
chore(release): 3.0.4
xiaodoudou Oct 6, 2026
1752df5
chore: merge release 3.0.4 from main
xiaodoudou Oct 6, 2026
2b0bd33
fix(security): files-only group cannot write records, CSRF check igno…
xiaodoudou Oct 6, 2026
3bd1aec
feat(examples): add the docs platform, an advanced example with a CMS…
xiaodoudou Oct 6, 2026
09b9dbe
test(examples): hold every example to the same bar
xiaodoudou Oct 6, 2026
8dd0ef9
feat(examples): add Boardwalk, a Vue 3 task board over the REST API
xiaodoudou Oct 6, 2026
f9f9f01
fix: exit with 0 when the CMS is stopped by a signal
xiaodoudou Oct 7, 2026
16a2296
feat(examples): add the Docker example with every secret in a .env
xiaodoudou Oct 6, 2026
910c20e
docs: shorten the sentences and lists, and the changelog
xiaodoudou Oct 7, 2026
acbd7cb
build: enforce Conventional Commits with a commit-msg hook
xiaodoudou Oct 7, 2026
5f2b295
ci: check the commit messages and the title of a pull request into main
xiaodoudou Oct 7, 2026
d948c28
docs: ask for Conventional Commits in CONTRIBUTING
xiaodoudou Oct 7, 2026
9ebfa3e
chore(release): 3.0.5
xiaodoudou Oct 7, 2026
5303c7c
chore: merge release 3.0.5 from main
xiaodoudou Oct 7, 2026
59653d3
chore(deps): update dependencies within their ranges
xiaodoudou Oct 8, 2026
417d4a5
chore(deps): upgrade helmet to 8
xiaodoudou Oct 8, 2026
729782e
feat: add cms-backup and cms-restore
xiaodoudou Oct 8, 2026
2156b10
feat: add agent skills and the cms-skills command
xiaodoudou Oct 8, 2026
d2deb9c
chore(deps): upgrade body-parser to 2
xiaodoudou Oct 8, 2026
dee6b3b
chore(deps): upgrade express to 5
xiaodoudou Oct 8, 2026
fa14901
chore(deps): upgrade commander to 15
xiaodoudou Oct 8, 2026
d124929
chore(deps): upgrade p-all to 5
xiaodoudou Oct 8, 2026
077e8e6
chore(deps): upgrade mongodb to 7
xiaodoudou Oct 8, 2026
615b732
chore(deps): upgrade knip to 6
xiaodoudou Oct 8, 2026
7dea441
chore(deps): upgrade vite to 8
xiaodoudou Oct 8, 2026
6b164a7
chore(deps): upgrade vue-router to 5
xiaodoudou Oct 8, 2026
380e6db
ci: open dependabot pull requests against dev
xiaodoudou Oct 8, 2026
324006d
Merge pull request #14 from xiaodoudou/deps/in-range
xiaodoudou Oct 8, 2026
6d0237d
Merge pull request #15 from xiaodoudou/deps/helmet-8
xiaodoudou Oct 8, 2026
602c349
Merge pull request #16 from xiaodoudou/deps/body-parser-2
xiaodoudou Oct 8, 2026
547bbcb
Merge pull request #17 from xiaodoudou/deps/express-5
xiaodoudou Oct 8, 2026
acbc5de
Merge pull request #18 from xiaodoudou/deps/commander-15
xiaodoudou Oct 8, 2026
5029b31
Merge pull request #19 from xiaodoudou/deps/p-all-5
xiaodoudou Oct 8, 2026
760eceb
Merge pull request #20 from xiaodoudou/deps/mongodb-7
xiaodoudou Oct 8, 2026
5acd71d
Merge pull request #21 from xiaodoudou/deps/knip-6
xiaodoudou Oct 8, 2026
5a6378b
Merge pull request #22 from xiaodoudou/deps/vite-8
xiaodoudou Oct 8, 2026
f00fdd6
Merge pull request #23 from xiaodoudou/deps/vue-router-5
xiaodoudou Oct 8, 2026
3f44ebc
Merge pull request #13 from xiaodoudou/feat/backup-and-agent-skills
xiaodoudou Oct 8, 2026
f31ee90
Merge pull request #24 from xiaodoudou/ci/dependabot-target-dev
xiaodoudou Oct 8, 2026
121b330
fix(admin): give the rich text toolbar the tint of the Markdown toolbar
xiaodoudou Oct 8, 2026
e5609ae
feat(admin): let a mask force upper or lower case
xiaodoudou Oct 8, 2026
e5efe6a
Merge pull request #25 from xiaodoudou/fix/wysiwyg-toolbar-background
xiaodoudou Oct 8, 2026
4a8209c
Merge pull request #26 from xiaodoudou/feat/mask-letter-case
xiaodoudou Oct 8, 2026
df7116e
docs(fields): retake the mask screenshots with the forced capitals
xiaodoudou Oct 8, 2026
5dda477
Merge pull request #27 from xiaodoudou/docs/mask-case-screenshots
xiaodoudou Oct 8, 2026
9443134
test(examples): stop the csrf token test from failing one time in 64
xiaodoudou Oct 8, 2026
41fa2c1
Merge pull request #28 from xiaodoudou/fix/flaky-csrf-test
xiaodoudou Oct 8, 2026
1468a65
chore(release): 3.0.6
xiaodoudou Oct 8, 2026
e09c79d
chore: merge release 3.0.6 from main
xiaodoudou Oct 8, 2026
b9ebac6
chore(deps-dev): bump jsdom from 29.1.1 to 30.1.2
dependabot[bot] Oct 8, 2026
01a1815
test(sync): stop the burst test from failing on a busy machine
xiaodoudou Oct 8, 2026
b6cf76c
Merge pull request #31 from xiaodoudou/fix/flaky-sync-burst-test
xiaodoudou Oct 8, 2026
a54f8b1
Merge pull request #30 from xiaodoudou/dependabot/npm_and_yarn/dev/js…
xiaodoudou Oct 8, 2026
eeaf65a
build(deps): drop del-cli, the last source of audit warnings
xiaodoudou Oct 9, 2026
f9558fe
refactor: move the dev clean-up of src/plugins to a script
xiaodoudou Oct 9, 2026
09e0e7c
build(deps): read a stream into a buffer with stream/consumers, drop …
xiaodoudou Oct 9, 2026
82a0c4b
build(deps): ask yes or no with readline, drop prompt
xiaodoudou Oct 9, 2026
83d4184
fix(security): keep the session files in a folder only the server can…
xiaodoudou Oct 9, 2026
40969de
fix(security): leave the sessions out of a cms-backup files copy
xiaodoudou Oct 9, 2026
f8a024d
Merge pull request #32 from xiaodoudou/fix/drop-del-cli
xiaodoudou Oct 9, 2026
e029770
Merge remote-tracking branch 'origin/dev' into build/drop-abandoned-deps
xiaodoudou Oct 9, 2026
2aeef30
Merge pull request #33 from xiaodoudou/build/drop-abandoned-deps
xiaodoudou Oct 9, 2026
5833f2c
Merge pull request #34 from xiaodoudou/fix/private-session-files
xiaodoudou Oct 9, 2026
59a1c70
chore(release): 3.0.7
xiaodoudou Oct 9, 2026
1de10f2
chore: merge release 3.0.7 from main
xiaodoudou Oct 9, 2026
c3507d8
chore(knip): clean up what knip 6 reports
xiaodoudou Oct 9, 2026
a35b9f5
Merge pull request #36 from xiaodoudou/build/knip-6-cleanup
xiaodoudou Oct 9, 2026
b7e2fc2
fix(dev): keep the page host in the Vite proxy
xiaodoudou Oct 9, 2026
2db3e77
fix(fields): keep the title of a block with no summary next to the grip
xiaodoudou Oct 9, 2026
b062711
feat(admin): nest menu groups to any depth
xiaodoudou Oct 9, 2026
87b935b
docs: add a page on resource files
xiaodoudou Oct 9, 2026
f840937
Merge pull request #37 from xiaodoudou/feat/nested-menu-groups
xiaodoudou Oct 11, 2026
6baa973
chore(release): 3.1.0
xiaodoudou Oct 11, 2026
7a3460f
chore: merge release 3.1.0 from main
xiaodoudou Oct 11, 2026
ec41308
build: support Node 24 and run CI on it
xiaodoudou Oct 11, 2026
9b45030
build: move the Docker example and the release jobs to Node 24
xiaodoudou Oct 11, 2026
89eae6f
fix(import): do not ask again once the input has ended
xiaodoudou Oct 11, 2026
07002c9
docs: note the confirm fix that Node 24 found in the changelog
xiaodoudou Oct 11, 2026
1088c29
docs: fix a line break in the changelog entry
xiaodoudou Oct 11, 2026
4cc29de
build: require Node 24 and drop Node 22
xiaodoudou Oct 11, 2026
50c6b8a
Merge pull request #39 from xiaodoudou/ci/node-24
xiaodoudou Oct 11, 2026
136ab76
chore(release): 3.1.1
xiaodoudou Oct 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: 22
node-version: 24
registry-url: https://registry.npmjs.org
# trusted publishing needs npm 11.5.1 or later; not npm 12, which refuses by default the dependencies fetched from a URL (vue3-shortkey is one)
- run: npm install -g 'npm@^11.5.1'
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
fetch-depth: 0
- uses: actions/setup-node@v7
with:
node-version: 22
node-version: 24
- name: Commits of the pull request
if: github.event_name == 'pull_request'
run: node scripts/commitlint.js --range "$BASE..$HEAD"
Expand Down Expand Up @@ -48,7 +48,7 @@ jobs:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: 22
node-version: 24
cache: npm
- run: npm ci
- name: Lint
Expand Down Expand Up @@ -96,7 +96,7 @@ jobs:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: 22
node-version: 24
cache: npm
- run: npm ci
- name: Driver contract suite
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ What changed in each version of Embed CMS, from 3.0.0 on, newest first. The vers

## [Unreleased]

## [3.1.1] - 2026-10-11

### Changed

- **Node 24 is the version Embed CMS requires, and Node 22 no longer is.** `engines` was `^22.12.0`. It is now `^24.0.0`, so installing on Node 22 prints an engine warning. CI runs every job on Node 24, and the Docker example runs on `node:24-bookworm-slim`.

### Fixed

- **`cms-import` and `cms-import-remote` crashed on Node 24 when their input ended right after a wrong answer.** Asked again after the wrong answer, the question was put to a closed input, which Node 24 refuses with `ERR_USE_AFTER_CLOSE`. It now answers no, as it does when the input closes before any answer.

## [3.1.0] - 2026-10-11

### Added
Expand Down Expand Up @@ -221,6 +231,7 @@ The release that turned node-cms into a project that stands on its own: the firs
- A delete goes to the replication peers right away again, `cms-import` prints no empty progress bars into logs, the xlsx import answers `400` without a file.

[Unreleased]: https://github.com/xiaodoudou/embed-cms/compare/v3.0.5...HEAD
[3.1.1]: https://github.com/xiaodoudou/embed-cms/compare/v3.1.0...v3.1.1
[3.1.0]: https://github.com/xiaodoudou/embed-cms/compare/v3.0.7...v3.1.0
[3.0.7]: https://github.com/xiaodoudou/embed-cms/compare/v3.0.6...v3.0.7
[3.0.6]: https://github.com/xiaodoudou/embed-cms/compare/v3.0.5...v3.0.6
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Thanks for helping. This page gets you from a clone to a change that passes CI:

## Setting up

You need Node.js 22.12 or later (CI runs Node 22) and git.
You need Node.js 24 (the version CI runs) and git.

```sh
git clone https://github.com/xiaodoudou/embed-cms.git embed-cms
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

> A headless CMS for Node.js: describe your content in JavaScript files, get an admin app, a REST API and a JavaScript API

[![License](https://img.shields.io/badge/License-GPL--3.0--only-blue?style=flat-square)](LICENSE) [![Node](https://img.shields.io/badge/Node-%3E%3D22.12-339933?style=flat-square)](#try-it-in-five-minutes) [![Storage](https://img.shields.io/badge/Storage-JSON%20%7C%20MongoDB%20%7C%20PostgreSQL-orange?style=flat-square)](docs/reference/CONFIG.md) [![Express](https://img.shields.io/badge/Express-mountable-lightgrey?style=flat-square)](docs/start/GETTING_STARTED.md) [![Locales](https://img.shields.io/badge/Content-translatable-blueviolet?style=flat-square)](docs/start/CONCEPTS.md) [![Tests](https://img.shields.io/badge/Tests-unit%20%7C%20security%20%7C%20frontend-brightgreen?style=flat-square)](docs/contributing/TESTING.md)
[![License](https://img.shields.io/badge/License-GPL--3.0--only-blue?style=flat-square)](LICENSE) [![Node](https://img.shields.io/badge/Node-24-339933?style=flat-square)](#try-it-in-five-minutes) [![Storage](https://img.shields.io/badge/Storage-JSON%20%7C%20MongoDB%20%7C%20PostgreSQL-orange?style=flat-square)](docs/reference/CONFIG.md) [![Express](https://img.shields.io/badge/Express-mountable-lightgrey?style=flat-square)](docs/start/GETTING_STARTED.md) [![Locales](https://img.shields.io/badge/Content-translatable-blueviolet?style=flat-square)](docs/start/CONCEPTS.md) [![Tests](https://img.shields.io/badge/Tests-unit%20%7C%20security%20%7C%20frontend-brightgreen?style=flat-square)](docs/contributing/TESTING.md)

You describe your content in plain JavaScript files, one per resource, and Embed CMS gives you three things from them: an admin app where editors write and translate that content, a REST API that serves it to your sites and apps, and a JavaScript API for your own server code.

Expand All @@ -18,7 +18,7 @@ It keeps your content in a LevelDB database on disk by default, so there is no d

## Try it in five minutes

You need [Node.js](https://nodejs.org/) 22.12 or later and git.
You need [Node.js](https://nodejs.org/) 24 and git.

```sh
git clone https://github.com/xiaodoudou/embed-cms.git embed-cms
Expand Down
4 changes: 2 additions & 2 deletions docs/examples/docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
# Built by scripts/build.sh.

# --- the modules: the only stage that needs the network and a compiler's worth of tools -----------------------------------
FROM node:22-bookworm-slim AS modules
FROM node:24-bookworm-slim AS modules
WORKDIR /app
# the lock file first: this layer is only made again when the dependencies change
COPY package.json package-lock.json ./
RUN npm ci --omit=dev --no-audit --no-fund

# --- the image that runs -------------------------------------------------------------------------------------------------
FROM node:22-bookworm-slim
FROM node:24-bookworm-slim
ENV NODE_ENV=production \
PORT=3000 \
DATA_DIR=/data
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/docker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ Put a proxy (nginx, Caddy or Traefik) on the machine and give it the https certi
|---|---|
| Change a secret (a leak, someone leaves) | Edit `.env`, or empty the line and run `./scripts/env.sh`. Then run `./scripts/start.sh`, and compose replaces the container with one that has the new value. Changing `AUTH_SECRET` or `SESSION_SECRET` signs everybody out and does nothing else. |
| Upgrade embed-cms | Raise `embed-cms` in `package.json` and run `npm install --package-lock-only`. Then run `./scripts/build.sh` and `./scripts/start.sh`. The data in the volume stays. |
| Back up | Stop the container first, because the databases are files that are written while it runs. Run `docker compose stop`, then `docker run --rm -v embed-cms-docker_data:/data -v "$PWD":/backup node:22-bookworm-slim tar czf /backup/data.tgz -C /data .`, then `./scripts/start.sh`. |
| Back up | Stop the container first, because the databases are files that are written while it runs. Run `docker compose stop`, then `docker run --rm -v embed-cms-docker_data:/data -v "$PWD":/backup node:24-bookworm-slim tar czf /backup/data.tgz -C /data .`, then `./scripts/start.sh`. |
| Use your own project | Copy this folder. Replace `resources/` and `content.json` (and add your site's routes to `server.js`). Keep the rest. Add every variable your code reads to `.env.example`. |
| Use another store | PostgreSQL and MongoDB read their credentials from the environment ([storage engines](../../reference/CONFIG.md#storage-engines)). Put `POSTGRES_USER` and `POSTGRES_PASSWORD` in `.env` like the other secrets, and add the database as one more service in `compose.yaml`. |

Expand Down
2 changes: 1 addition & 1 deletion docs/examples/docker/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion docs/examples/docker/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@
"express": "^4.18.2"
},
"engines": {
"node": "^22.12.0"
"node": "^24.0.0"
}
}
2 changes: 1 addition & 1 deletion docs/reference/CONFIG.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ Every resource keeps its records in a store, and you choose which kind with `dbE
| `dbEngine.type` | What it is | Needs |
|---|---|---|
| `leveldb` (the default) | a LevelDB folder per resource, read from disk | nothing (the `classic-level` package comes with embed-cms) |
| `sqlite` | one SQLite file per resource, read from disk | nothing (it is part of Node 22; Node marks it experimental) |
| `sqlite` | one SQLite file per resource, read from disk | nothing (it is part of Node; Node marks it experimental) |
| `jsondown` | all records in memory, saved to one JSON file per resource | nothing |
| `mongodb` | one collection per resource | a MongoDB server |
| `postgres` | one table per resource | a PostgreSQL server |
Expand Down
8 changes: 7 additions & 1 deletion lib/util/confirm.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ const readline = require('readline')
*/
async function confirm (question, { input = process.stdin, output = process.stdout } = {}) {
const rl = readline.createInterface({ input, output })
// an input that ended in the same chunk as a wrong answer has closed the interface by the time the question is asked again, and Node 24
// throws when a closed interface is prompted
let closed = false
rl.on('close', () => { closed = true })
rl.setPrompt(`${question} `)
rl.prompt()
try {
Expand All @@ -19,7 +23,9 @@ async function confirm (question, { input = process.stdin, output = process.stdo
return text === 'yes'
}
output.write('yes / no\n')
rl.prompt()
if (!closed) {
rl.prompt()
}
}
return false
} finally {
Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "embed-cms",
"version": "3.1.0",
"version": "3.1.1",
"description": "Content management system, written in node.js, uses leveldb as an asset and content store.",
"main": "index.js",
"types": "index.d.ts",
Expand Down Expand Up @@ -53,7 +53,7 @@
"migrate-store": "node scripts/migrateStore.js"
},
"engines": {
"node": "^22.12.0"
"node": "^24.0.0"
},
"repository": {
"type": "git",
Expand Down
2 changes: 1 addition & 1 deletion skills/embed-cms-create-site/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ The docs are in the `docs/` folder of https://github.com/xiaodoudou/embed-cms, n

## Steps

1. **Ask only what you need**: what the site is for, the content types, one language or several (`enUS`, `zhCN`). Node must be `^22.12.0`.
1. **Ask only what you need**: what the site is for, the content types, one language or several (`enUS`, `zhCN`). Node must be 24.
2. **Scaffold** in the project folder:
```sh
npm init -y && npm install embed-cms express
Expand Down