domma-cms 1.6.60 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (168) hide show
  1. package/CHANGELOG.md +4349 -0
  2. package/README.md +1 -1
  3. package/admin/dist/domma/domma-tools.css +3 -3
  4. package/admin/dist/domma/domma-tools.min.js +3 -3
  5. package/admin/js/lib/effect-defs.js +1 -1
  6. package/admin/js/lib/effects-builder.js +2 -2
  7. package/admin/js/lib/mail-compose.js +1 -0
  8. package/admin/js/lib/page-editor-reference.js +5 -5
  9. package/admin/js/lib/shortcode-tags.js +1 -1
  10. package/admin/js/templates/call-new.html +1 -1
  11. package/admin/js/templates/docs/usage-shortcodes.html +39 -0
  12. package/admin/js/views/call-new.js +1 -1
  13. package/admin/js/views/contacts.js +15 -15
  14. package/admin/js/views/form-submissions.js +2 -2
  15. package/docs/DommaFeatures.md +3005 -0
  16. package/docs/MultiTenant.md +176 -0
  17. package/docs/api-reference.md +1667 -0
  18. package/docs/cache.md +96 -0
  19. package/docs/configuration.md +1811 -0
  20. package/docs/editions-and-licences.md +190 -0
  21. package/docs/getting-started.md +201 -0
  22. package/docs/guides/form-triggers.md +260 -0
  23. package/docs/guides/mongodb-storage-adapter.md +282 -0
  24. package/docs/guides/multi-page-forms.md +121 -0
  25. package/docs/images/scribe-composer.png +0 -0
  26. package/docs/markdown-shortcodes.md +1738 -0
  27. package/docs/pentest-report-2026-04-03.md +181 -0
  28. package/docs/plans/2026-02-28-admin-topbar-login-forms.md +349 -0
  29. package/docs/plans/2026-02-28-domma-ui-polish.md +286 -0
  30. package/docs/plans/2026-02-28-reset-seed-fresh-commands.md +520 -0
  31. package/docs/plans/2026-03-02-cookie-consent-design.md +86 -0
  32. package/docs/plans/2026-03-02-cookie-consent-plugin.md +453 -0
  33. package/docs/plans/2026-03-02-tooltip-sweep-and-back-to-top-plugin-design.md +126 -0
  34. package/docs/plans/2026-03-02-tooltip-sweep-back-to-top.md +427 -0
  35. package/docs/plans/2026-03-05-cookie-consent-btt-core.md +115 -0
  36. package/docs/plans/2026-03-05-custom-css-migrate-to-core-design.md +35 -0
  37. package/docs/plans/2026-03-05-custom-css-migrate-to-core.md +352 -0
  38. package/docs/plans/2026-03-05-scribe-script-shortcode.md +373 -0
  39. package/docs/plans/2026-03-05-user-types-design.md +139 -0
  40. package/docs/plans/2026-03-05-user-types-implementation.md +1035 -0
  41. package/docs/plans/2026-03-09-page-editor-view-cta-inserts-design.md +78 -0
  42. package/docs/plans/2026-03-09-page-editor-view-cta-inserts.md +388 -0
  43. package/docs/plans/2026-03-09-pro-documentation-design.md +80 -0
  44. package/docs/plans/2026-03-09-pro-documentation.md +1017 -0
  45. package/docs/plans/2026-06-10-core-project-design.md +240 -0
  46. package/docs/plugin-development.md +827 -0
  47. package/docs/recruitment-recipe.md +501 -0
  48. package/docs/scaffolding.md +312 -0
  49. package/docs/screenshots/calculator-floating.png +0 -0
  50. package/docs/screenshots/calculator-standard.png +0 -0
  51. package/docs/screenshots/email-settings.png +0 -0
  52. package/docs/screenshots/messages-count.png +0 -0
  53. package/docs/structure/user-types.md +107 -0
  54. package/docs/superpowers/plans/2026-05-25-admin-sidebar-via-menus.md +1112 -0
  55. package/docs/superpowers/plans/2026-06-08-navbar-mobile-drawer-and-menu-enrichment.md +1161 -0
  56. package/docs/superpowers/plans/2026-06-25-domma-docs-project.md +695 -0
  57. package/docs/superpowers/plans/2026-06-26-surveys-HANDOFF.md +68 -0
  58. package/docs/superpowers/plans/2026-06-26-surveys-pro-plugin.md +1902 -0
  59. package/docs/superpowers/plans/2026-08-19-collection-context-sort-export.md +1577 -0
  60. package/docs/superpowers/plans/2026-10-09-content-api.md +1192 -0
  61. package/docs/superpowers/specs/2026-03-12-form-followup-actions-design.md +152 -0
  62. package/docs/superpowers/specs/2026-03-12-page-editor-form-insert-and-per-page-theme-design.md +115 -0
  63. package/docs/superpowers/specs/2026-03-17-nav-hidden-items-design.md +85 -0
  64. package/docs/superpowers/specs/2026-03-19-accordion-insert-design.md +175 -0
  65. package/docs/superpowers/specs/2026-03-25-static-block-shortcode-design.md +153 -0
  66. package/docs/superpowers/specs/2026-03-25-text-shortcode-design.md +168 -0
  67. package/docs/superpowers/specs/2026-04-05-card-builder-design.md +315 -0
  68. package/docs/superpowers/specs/2026-04-06-insert-builders-design.md +278 -0
  69. package/docs/superpowers/specs/2026-04-06-layouts-design.md +226 -0
  70. package/docs/superpowers/specs/2026-04-07-blog-plugin-design.md +300 -0
  71. package/docs/superpowers/specs/2026-04-07-calendar-plugin-design.md +538 -0
  72. package/docs/superpowers/specs/2026-04-17-components-area-design.md +368 -0
  73. package/docs/superpowers/specs/2026-05-02-effects-slideover-overhaul-design.md +193 -0
  74. package/docs/superpowers/specs/2026-05-06-dashboard-rebuild-design.md +257 -0
  75. package/docs/superpowers/specs/2026-05-24-menus-design.md +466 -0
  76. package/docs/superpowers/specs/2026-05-25-admin-sidebar-via-menus-design.md +358 -0
  77. package/docs/superpowers/specs/2026-05-25-projects-design.md +380 -0
  78. package/docs/superpowers/specs/2026-06-08-navbar-mobile-drawer-and-menu-enrichment-design.md +292 -0
  79. package/docs/superpowers/specs/2026-06-08-sidebar-tools-plugins-folders-design.md +59 -0
  80. package/docs/superpowers/specs/2026-06-25-domma-docs-project-design.md +192 -0
  81. package/docs/superpowers/specs/2026-06-26-domma-charts-upstream-proposal.md +44 -0
  82. package/docs/superpowers/specs/2026-06-26-manager-scheduler-upstream-proposal.md +46 -0
  83. package/docs/superpowers/specs/2026-06-26-surveys-pro-plugin-design.md +206 -0
  84. package/docs/superpowers/specs/2026-07-02-shortcode-context-menu-design.md +96 -0
  85. package/docs/superpowers/specs/2026-08-19-collection-context-sort-export-design.md +330 -0
  86. package/docs/superpowers/specs/2026-09-22-dcms-marketplace-design.md +1150 -0
  87. package/docs/superpowers/specs/2026-10-09-content-api-design.md +325 -0
  88. package/docs/superpowers/specs/plans/2026-03-12-form-followup-actions.md +624 -0
  89. package/docs/superpowers/specs/plans/2026-03-12-page-editor-form-insert-and-per-page-theme.md +125 -0
  90. package/docs/superpowers/specs/plans/2026-03-17-nav-hidden-items.md +578 -0
  91. package/docs/superpowers/specs/plans/2026-03-19-accordion-insert.md +635 -0
  92. package/docs/superpowers/specs/plans/2026-03-25-text-shortcode.md +545 -0
  93. package/docs/superpowers/specs/plans/2026-04-05-card-builder.md +1970 -0
  94. package/docs/superpowers/specs/plans/2026-04-06-insert-builders.md +1049 -0
  95. package/docs/superpowers/specs/plans/2026-04-06-layouts.md +1015 -0
  96. package/docs/superpowers/specs/plans/2026-04-07-calendar-plugin.md +1526 -0
  97. package/docs/superpowers/specs/plans/2026-04-08-plugin-monetisation-split.md +242 -0
  98. package/docs/superpowers/specs/plans/2026-04-17-components-area.md +2038 -0
  99. package/docs/superpowers/specs/plans/2026-05-02-effects-slideover-overhaul.md +2335 -0
  100. package/docs/superpowers/specs/plans/2026-05-06-dashboard-rebuild.md +1999 -0
  101. package/docs/superpowers/specs/plans/2026-05-17-cache-system.md +1436 -0
  102. package/docs/superpowers/specs/plans/2026-05-24-menus.md +3096 -0
  103. package/docs/superpowers/specs/plans/2026-05-25-projects.md +2869 -0
  104. package/docs/superpowers/specs/plans/2026-09-22-marketplace-step2-consolidation.md +505 -0
  105. package/docs/superpowers/specs/plans/2026-09-22-marketplace-step3-catalogue-and-key.md +154 -0
  106. package/docs/superpowers/specs/plans/2026-09-22-tools-promotion.md +260 -0
  107. package/docs/theming.md +320 -0
  108. package/package.json +2 -2
  109. package/plugins/_lib/admin/mail/compose-window.js +3 -1
  110. package/plugins/_lib/admin/mail/identity.js +18 -3
  111. package/plugins/_lib/admin/mail/reader-view.js +32 -3
  112. package/plugins/blog/CLAUDE.md +4 -0
  113. package/plugins/blog/admin/lib/email.js +191 -0
  114. package/plugins/blog/admin/views/comments.js +3 -1
  115. package/plugins/blog/plugin.json +2 -2
  116. package/plugins/blog/plugin.public.js +1 -1
  117. package/plugins/blog/tests/email.test.js +69 -0
  118. package/plugins/booking/CLAUDE.md +4 -0
  119. package/plugins/booking/admin/lib/email.js +191 -0
  120. package/plugins/booking/admin/views/panels.js +7 -3
  121. package/plugins/booking/plugin.json +1 -1
  122. package/plugins/booking/tests/email.test.js +69 -0
  123. package/plugins/free-tier.lock.json +27 -19
  124. package/plugins/shopping-cart/CLAUDE.md +4 -0
  125. package/plugins/shopping-cart/admin/lib/email.js +191 -0
  126. package/plugins/shopping-cart/admin/views/orders.js +11 -3
  127. package/plugins/shopping-cart/plugin.json +2 -2
  128. package/plugins/shopping-cart/tests/email.test.js +69 -0
  129. package/plugins/support/CLAUDE.md +4 -0
  130. package/plugins/support/admin/lib/email.js +191 -0
  131. package/plugins/support/admin/views/desk.js +4 -1
  132. package/plugins/support/admin/views/inbox.js +6 -2
  133. package/plugins/support/plugin.json +2 -2
  134. package/plugins/support/tests/email.test.js +69 -0
  135. package/public/js/celebrations/core/canvas.js +1 -1
  136. package/public/js/celebrations/index.js +1 -1
  137. package/public/js/celebrations/licenses/ABeeZee-Regular-OFL.txt +93 -0
  138. package/public/js/celebrations/licenses/Allura-Regular-OFL.txt +93 -0
  139. package/public/js/celebrations/message-attrs.mjs +1 -0
  140. package/public/js/celebrations/themes/anniversary.js +1 -0
  141. package/public/js/celebrations/themes/autumn.js +1 -0
  142. package/public/js/celebrations/themes/birthday.js +1 -0
  143. package/public/js/celebrations/themes/butterfly-flight.js +1 -0
  144. package/public/js/celebrations/themes/calendar.js +1 -0
  145. package/public/js/celebrations/themes/chinese-new-year-dates.js +1 -0
  146. package/public/js/celebrations/themes/chinese-new-year.js +1 -0
  147. package/public/js/celebrations/themes/christmas.js +1 -1
  148. package/public/js/celebrations/themes/easter.js +1 -0
  149. package/public/js/celebrations/themes/garden-drawing.js +1 -0
  150. package/public/js/celebrations/themes/garden.js +1 -0
  151. package/public/js/celebrations/themes/graduation.js +1 -0
  152. package/public/js/celebrations/themes/greeting.js +1 -0
  153. package/public/js/celebrations/themes/make-it-rain.js +1 -0
  154. package/public/js/celebrations/themes/money-rain.js +1 -0
  155. package/public/js/celebrations/themes/new-year.js +1 -0
  156. package/public/js/celebrations/themes/occasion-drawing.js +1 -0
  157. package/public/js/celebrations/themes/occasions.js +1 -0
  158. package/public/js/celebrations/themes/rain-control.js +1 -0
  159. package/public/js/celebrations/themes/sparkler-font-data.js +1 -0
  160. package/public/js/celebrations/themes/sparkler-font.js +1 -0
  161. package/public/js/celebrations/themes/sparkler-writing.js +1 -0
  162. package/public/js/celebrations/themes/summer-garden.js +1 -0
  163. package/public/js/celebrations/themes/winter.js +1 -0
  164. package/public/js/celebrations/trait-data.mjs +1 -1
  165. package/public/js/effects.js +1 -1
  166. package/scripts/build.js +4 -0
  167. package/server/services/markdown.js +5 -2
  168. package/server/templates/page.html +1 -1
@@ -0,0 +1,190 @@
1
+ # Editions and licences
2
+
3
+ What you get free with Domma CMS, what is paid, what "Pro" means, and how plugin licences work.
4
+ Written for site owners. Prices: TBC.
5
+
6
+ ## In short
7
+
8
+ - The CMS itself is free. Every core feature works without a licence.
9
+ - Some plugins are free and ship with the CMS. Others are paid and need a licence.
10
+ - A "Pro" plugin adds to, or replaces, a free Tool or plugin. If its licence lapses, the free one comes back.
11
+ - A licence is either a **rental** (a site the Domma Manager runs for you) or **perpetual** (bought outright).
12
+ - A rental stops when its term and grace period end. A perpetual licence never stops; only support and updates end.
13
+ - A few features need MongoDB. One plugin, MongoDB Adapter, is only for sites run by the Domma Manager.
14
+
15
+ ## What the free CMS includes
16
+
17
+ Everything in the core CMS is free:
18
+
19
+ - **Content** - pages with a visual editor, version history, drafts and share links, shortcodes, blocks,
20
+ components and a media library.
21
+ - **Design** - built-in themes, menus, right-click menus and a visitor theme switcher.
22
+ - **Data** - collections on file storage, saved views, a form builder, and public collection displays.
23
+ - **API** - the `/api/v1` collection API, the `/api/content/v1` Content API, API tokens and API Builder endpoints.
24
+ - **Admin** - dashboard, notifications, in-admin docs, projects, roles and permissions.
25
+ - **Built-in Tools** - Notes, Todo, Analytics, Contacts and SEO. Each can be switched off in the
26
+ Marketplace under "Built-in Tools".
27
+ - **Marketplace** - installing, updating and switching plugins.
28
+
29
+ ## Core features that need MongoDB
30
+
31
+ These are marked "Pro" in the CMS. They are not licensed. They switch on when the site has a MongoDB
32
+ connection in `config/connections.json`:
33
+
34
+ - **MongoDB storage** - keep any collection in MongoDB instead of files. Set it per collection on the
35
+ collection's Storage tab.
36
+ - **Actions** - workflows that run steps against a collection entry. Without MongoDB the Actions screen
37
+ says they need MongoDB.
38
+
39
+ Add a connection under **Data > Collections > Database connections** (admins only), or with
40
+ `npm run pro enable`. On a site run by the Domma Manager, the MongoDB Adapter plugin sets the connection
41
+ up for you (see below).
42
+
43
+ The optional Redis cache driver is also described as a Pro feature. It needs Redis, not a licence.
44
+ See `docs/cache.md`.
45
+
46
+ ## Free plugins
47
+
48
+ These are marked `free` in their manifests and ship in the CMS `plugins/` folder. Switch them on in the
49
+ Marketplace.
50
+
51
+ - **Blog** - posts, categories and comments.
52
+ - **Feedback** - tell Domma what is broken, missing or good, from your admin.
53
+ - **Mail Reader** - a read-only IMAP mailbox reader.
54
+ - **Security** - a health check, sign-in lockout, password rules and a sign-in log.
55
+ - **Shopping Cart** - products, a storefront, a cart and checkout.
56
+
57
+ ## Paid plugins
58
+
59
+ Every other plugin in the Marketplace is paid. A paid plugin is marked closed source. It needs a valid
60
+ licence on the site, or it does not start. Paid plugins cannot be viewed or exported from the Marketplace.
61
+
62
+ A plugin you write yourself is never asked for a licence.
63
+
64
+ ## What "Pro" means
65
+
66
+ A Pro plugin builds on a free Tool or plugin. It does this in one of two ways:
67
+
68
+ - **It replaces it** (`supersedes` in its manifest). The free one stops loading while the Pro one runs,
69
+ so you see one screen, not two. For a built-in Tool, the Pro plugin hides the Tool's sidebar entry and
70
+ takes over its screen. The Tool's data and API stay in place.
71
+ - **It adds to it** (`requires` in its manifest). Both run. If the free one is switched off, the Pro one
72
+ does not start.
73
+
74
+ | Pro plugin | Relationship |
75
+ |---|---|
76
+ | Blog Pro | Replaces Blog |
77
+ | Contacts Pro | Requires and replaces the built-in Contacts Tool |
78
+ | Email (email-pro) | Replaces Mail Reader |
79
+ | Security Pro | Replaces Security |
80
+ | SEO Pro | Requires the built-in SEO Tool |
81
+ | Shopping Cart Pro | Requires Shopping Cart |
82
+ | Analytics Pro | Separate from the built-in Analytics Tool; neither replaces the other |
83
+ | Social Media Pro | No free edition |
84
+ | Waypoint Pro | No free edition |
85
+
86
+ ### When a Pro licence lapses
87
+
88
+ The replacement is worked out each time the site starts. Nothing is written to your settings. So when a Pro
89
+ plugin stops running because its licence has lapsed:
90
+
91
+ - the free plugin it replaced loads again on the next start, and
92
+ - a built-in Tool it took over comes back.
93
+
94
+ You are never left with less than a site that never bought the Pro plugin.
95
+
96
+ ## Licences
97
+
98
+ ### Where the licence lives
99
+
100
+ A licence is a signed file called an entitlement. The CMS looks for it in two places, in this order:
101
+
102
+ 1. `plugins/<plugin>/.entitlement.json` - one plugin, one licence. A `.dcmsplugin` file carries it in.
103
+ 2. `config/entitlements/*.json` - site-wide licences.
104
+
105
+ The file must be signed by the Domma Marketplace key. A missing, edited or wrongly signed file counts as
106
+ unlicensed, and the plugin does not start.
107
+
108
+ The licence is checked each time the site starts. A plugin that is refused is not switched off in your
109
+ settings, so renewing brings it straight back on the next start.
110
+
111
+ ### Rental
112
+
113
+ For a site run for you by the Domma Manager. The plugin is rented monthly alongside the hosting.
114
+
115
+ - The plugin banner shows **Expires** and the date.
116
+ - After the end date there is a grace period. The plugin keeps running and the banner shows
117
+ **Expired (date) (grace)**. The Marketplace marks it **Renew**. The grace period is set on the licence;
118
+ the Manager issues 7 days unless told otherwise.
119
+ - After the grace period the plugin does not start. The Marketplace marks it **Expired**. Its data is kept.
120
+ - A notice appears 14 days before the end date, during the grace period, and once it has stopped.
121
+
122
+ ### Perpetual
123
+
124
+ For a site the Domma Manager does not run. You buy the plugin once, with a period of support.
125
+
126
+ - The plugin banner shows **Support to** and the date.
127
+ - When support ends, the banner shows **Support ended**. The plugin keeps running for good.
128
+ - What ends is support and updates. Renewing support extends it.
129
+ - A notice tells you when support and updates have ended.
130
+
131
+ ## Managed-only plugins
132
+
133
+ **MongoDB Adapter** is only offered for sites run by the Domma Manager. The Manager creates a database and a
134
+ user for the site, and writes the site's connection file. On a site the Manager does not run, the plugin
135
+ would have nothing to do.
136
+
137
+ When the Manager removes it, the site's connection file and database user are removed. The database itself
138
+ is kept.
139
+
140
+ ## Plugins that need MongoDB
141
+
142
+ - **MongoDB Adapter** - provides MongoDB to a managed site.
143
+ - **Email (email-pro)** - search, threads, rules, scheduled sends, snooze and vacation replies need MongoDB.
144
+ Without it, reading, filing and sending still work.
145
+ - **Data Transfer** - needs MongoDB only to move collections to or from MongoDB. Backups, restores and
146
+ clones work on file storage.
147
+ - **Surveys** - uses MongoDB when there is a connection, and falls back to file storage when there is not.
148
+
149
+ Garage and Messages work on either storage. The rest do not use MongoDB.
150
+
151
+ ## All Marketplace plugins
152
+
153
+ | Plugin | Tier | Needs MongoDB | Managed-only | Notes |
154
+ |---|---|---|---|---|
155
+ | Analytics Pro | paid | No | No | Separate from the built-in Analytics Tool |
156
+ | Blog | free | No | No | Ships with the CMS |
157
+ | Blog Pro | paid | No | No | Replaces Blog |
158
+ | Calendar | paid | No | No | Uses Contacts, Notes and Todo when they are on |
159
+ | Contacts Pro | paid | No | No | Requires and replaces the built-in Contacts Tool |
160
+ | Data Transfer | paid | Only to move to or from MongoDB | No | Backups and restores work on file storage |
161
+ | Docs | paid | No | No | |
162
+ | Email (email-pro) | paid | Partly | No | Replaces Mail Reader; some features need MongoDB |
163
+ | Feedback | free | No | No | Ships with the CMS |
164
+ | Garage | paid | No | No | Works on file or MongoDB storage |
165
+ | Invoices | paid | No | No | Uses Contacts |
166
+ | Job Board | paid | No | No | |
167
+ | Mail Reader | free | No | No | Ships with the CMS |
168
+ | Messages | paid | No | No | File storage unless moved to MongoDB |
169
+ | MongoDB Adapter | paid | Provides it | Yes | Set up by the Domma Manager |
170
+ | Security | free | No | No | Ships with the CMS |
171
+ | Security Pro | paid | No | No | Replaces Security |
172
+ | SEO Pro | paid | No | No | Requires the built-in SEO Tool |
173
+ | Shopping Cart | free | No | No | Ships with the CMS |
174
+ | Shopping Cart Pro | paid | No | No | Requires Shopping Cart |
175
+ | Social Media Pro | paid | No | No | Uses SEO, Calendar and Blog when they are on |
176
+ | Surveys | paid | Optional | No | Falls back to file storage |
177
+ | Theme Roller | paid | No | No | |
178
+ | Waypoint Pro | paid | No | No | |
179
+
180
+ ## Getting a licence
181
+
182
+ Prices: TBC.
183
+
184
+ - **A site run by the Domma Manager** - open **Marketplace > Browse**. It lists what your Manager offers.
185
+ Install brings a plugin in already licensed. A plugin not licensed yet is still listed; ask for it to be
186
+ added.
187
+ - **Any other site** - buy the plugin and you receive a single `.dcmsplugin` file. Use **Install from
188
+ file** in the Marketplace banner. The same button installs later updates.
189
+
190
+ To buy a plugin or renew a licence, contact Domma CMS.
@@ -0,0 +1,201 @@
1
+ # Getting Started with Domma CMS
2
+
3
+ ## Prerequisites
4
+
5
+ - **Node.js** 24 or later
6
+ - **npm** 11 or later (bundled with Node 24+)
7
+ - A terminal / command prompt
8
+
9
+ ## Quick Start
10
+
11
+ The fastest way to create a new site is via `npx`, which requires no global install:
12
+
13
+ ```bash
14
+ npx domma-cms@latest my-site
15
+ cd my-site
16
+ npm start
17
+ ```
18
+
19
+ This scaffolds a new project in the `my-site/` directory and then, in one go:
20
+
21
+ 1. runs `npm install`,
22
+ 2. runs the terminal setup wizard (`npm run setup`, described below),
23
+ 3. seeds the default pages, forms and collections (`npm run seed`),
24
+ 4. writes a `.domma` version marker used by `npx domma-cms update`.
25
+
26
+ You do not need to run `npm install` yourself. Options:
27
+
28
+ | Flag | Effect |
29
+ |---|---|
30
+ | `--no-install` | Skip `npm install` (this also skips the setup wizard) |
31
+ | `--no-setup` | Skip the terminal setup wizard - you can create the first admin in the browser instead |
32
+ | `--no-seed` | Skip seeding default pages, forms and collections |
33
+ | `--help` | Show usage |
34
+
35
+ To update an existing project later, run `npx domma-cms update` from inside it (`--dry-run` previews the changes).
36
+
37
+ ## What the Scaffolder Creates
38
+
39
+ ```
40
+ my-site/
41
+ ├── bin/ # CLI entry point
42
+ ├── config/ # All configuration JSON files
43
+ │ ├── auth.json
44
+ │ ├── content.json
45
+ │ ├── menus/ # Menu definitions (navbar, footer, etc.)
46
+ │ ├── navigation.json
47
+ │ ├── plugins.json
48
+ │ ├── presets.json # Page layout presets
49
+ │ ├── server.json
50
+ │ └── site.json
51
+ ├── content/ # All content as flat files
52
+ │ ├── collections/ # Collection data (JSON entries)
53
+ │ ├── media/ # Uploaded media files
54
+ │ ├── pages/ # Markdown pages
55
+ │ └── users/ # User accounts (JSON)
56
+ ├── plugins/ # Bundled plugins
57
+ │ ├── blog/
58
+ │ ├── mail-reader/
59
+ │ ├── security/
60
+ │ └── shopping-cart/
61
+ ├── admin/ # Admin SPA (Domma + Fastify)
62
+ │ ├── css/
63
+ │ ├── js/
64
+ │ └── index.html
65
+ ├── public/ # Public site assets
66
+ │ ├── css/site.css
67
+ │ └── js/site.js
68
+ ├── scripts/ # Utility scripts (setup, seed, reset)
69
+ ├── server/ # Fastify server
70
+ │ ├── middleware/
71
+ │ ├── routes/
72
+ │ ├── services/
73
+ │ └── server.js
74
+ ├── .env # Secrets only (JWT_SECRET, NODE_ENV, ...)
75
+ └── .domma # Version marker used by `npx domma-cms update`
76
+ ```
77
+
78
+ Other `content/` folders (blocks, forms, versions, sessions and so on) are created as the CMS needs them.
79
+
80
+ ## Running the Setup Wizard
81
+
82
+ The scaffolder runs the setup wizard for you. You can run it again at any time:
83
+
84
+ ```bash
85
+ npm run setup
86
+ ```
87
+
88
+ The terminal wizard works through these steps, skipping any that are already done:
89
+
90
+ 1. **JWT secret** - generates a secure `JWT_SECRET` in `.env` (skipped if one is already set)
91
+ 2. **Instance secret** - generates `INSTANCE_SECRET` in `.env` (skipped if already set); Mail Reader seals stored mailbox passwords with it
92
+ 3. **Admin account** - only if no users exist: asks for your full name, email address and a password (minimum 8 characters), and creates a Super Admin in `content/users/<uuid>.json`
93
+ 4. **Site identity** - site title and tagline, written to `config/site.json` and the navbar brand (the SMTP From name follows the title while it still matches the old one)
94
+ 5. **Theme** - pick one of the bundled themes (Enter keeps `charcoal-dark`)
95
+ 6. **Port** - the server port (Enter keeps 4096), written to `config/server.json`
96
+
97
+ ### Setting up in the browser instead
98
+
99
+ If you skipped the terminal wizard (`--no-setup`), open `/admin` while no users exist. The admin shows a setup form to create the first Super Admin, followed by a short onboarding wizard: name the site, pick a theme, done. Browser setup is refused once any user exists.
100
+
101
+ ## Starting the Server
102
+
103
+ ```bash
104
+ npm start
105
+ ```
106
+
107
+ For development with automatic restarts on file changes:
108
+
109
+ ```bash
110
+ npm run dev
111
+ ```
112
+
113
+ The server starts on port **4096** by default. Open `http://localhost:4096` to see your public site and `http://localhost:4096/admin` for the admin panel.
114
+
115
+ ## First Login
116
+
117
+ 1. Navigate to `http://localhost:4096/admin`
118
+ 2. Enter the email and password you provided during setup
119
+ 3. You will be issued a JWT access token (15 min expiry) and a refresh token (7 day expiry) - these are stored in the browser and refreshed automatically
120
+
121
+ If you ever get locked out, use the user management script rather than a reset - for example `npm run users -- reset-password you@example.com` or `npm run users -- list`. (`npm run reset` is a full factory reset that also deletes your pages, media and collections - see below.) If the Security plugin's lockout has blocked you, run `node plugins/security/bin/unlock.js --all`.
122
+
123
+ ## Creating Your First Page
124
+
125
+ 1. In the admin sidebar, click **Pages**
126
+ 2. Click **New Page**
127
+ 3. Set a **URL path** (e.g. `/about`) - this maps directly to the public URL
128
+ 4. Give the page a **title** and choose a **layout** (for example default, with-sidebar, landing or article)
129
+ 5. Write content using Markdown in the editor; shortcodes such as `[card]`, `[grid]`, and `[slideover]` are supported
130
+ 6. Set **Status** to `published` and click **Save**
131
+
132
+ The page is immediately available at `http://localhost:4096/about`.
133
+
134
+ ## What's Included by Default
135
+
136
+ ### Themes
137
+
138
+ Twenty-eight themes ship out of the box - fourteen colour palettes each in a dark and a light variant:
139
+
140
+ | Palette | Dark | Light |
141
+ |---|---|---|
142
+ | Charcoal | charcoal-dark | charcoal-light |
143
+ | Ocean | ocean-dark | ocean-light |
144
+ | Forest | forest-dark | forest-light |
145
+ | Sunset | sunset-dark | sunset-light |
146
+ | Royal | royal-dark | royal-light |
147
+ | Lemon | lemon-dark | lemon-light |
148
+ | Silver | silver-dark | silver-light |
149
+ | Grayve | grayve-dark | grayve-light |
150
+ | Mint | mint-dark | mint-light |
151
+ | Unicorn | unicorn-dark | unicorn-light |
152
+ | Dreamy | dreamy-dark | dreamy-light |
153
+ | Christmas | christmas-dark | christmas-light |
154
+ | Wedding | wedding-dark | wedding-light |
155
+ | Corporate | corporate-dark | corporate-light |
156
+
157
+ The public site theme and the admin theme are set independently in **Settings**.
158
+
159
+ ### Built-in features that used to be plugins
160
+
161
+ Analytics (page-hit tracking), effects (scroll-triggered animations and the effect shortcodes) and the public theme switcher are now part of the core CMS - there is nothing to install or enable.
162
+
163
+ ### Plugins
164
+
165
+ Four free plugins are bundled in `plugins/`:
166
+
167
+ - **blog** - public blog with posts, categories and comments
168
+ - **mail-reader** - read-only IMAP mailbox reader inside the admin
169
+ - **security** - health check, sign-in lockout, password rules, sign-in log and scanner blocking
170
+ - **shopping-cart** - products, storefront, cart and checkout (Stripe, PayPal or offline payment)
171
+
172
+ A new project starts with all four disabled - enable the ones you want from the **Marketplace** screen in the admin (enabling Security is recommended). When an existing site is updated with `npx domma-cms update`, Security arrives switched on. Paid plugins (Theme Roller, Blog Pro and others) are installed from the Marketplace or from a `.dcmsplugin` file.
173
+
174
+ ### Page Layouts
175
+
176
+ Nine layout presets are included (defined in `config/presets.json`):
177
+
178
+ | Key | Description |
179
+ |---|---|
180
+ | `default` | Standard page with navbar and footer |
181
+ | `with-sidebar` | Page with navbar, sidebar, and footer |
182
+ | `minimal` | Clean page with no navbar or footer |
183
+ | `blank` | Minimal page with no navbar or footer |
184
+ | `landing` | Full-width landing page with navbar, no footer |
185
+ | `article` | Narrow reading column for long-form prose and blog posts |
186
+ | `product` | Full-width marketing page that keeps the footer |
187
+ | `dashboard` | Wide layout for data-heavy or app-like pages; no footer |
188
+ | `wide` | Standard page using a wide content column (about 75% of the viewport) |
189
+
190
+ ### npm Scripts
191
+
192
+ | Script | Purpose |
193
+ |---|---|
194
+ | `npm start` | Start the server |
195
+ | `npm run dev` | Start with `--watch` for development |
196
+ | `npm run setup` | Interactive setup wizard (secrets, first admin, site identity, theme, port) |
197
+ | `npm run seed` | Populate default pages, forms and collections |
198
+ | `npm run users -- <command>` | Command-line user management (`list`, `reset-password`, `set-role`, `create`, ...) |
199
+ | `npm run reset` | **Factory reset** (asks you to type `yes`): deletes all users, pages, media, collections (except roles) and form data, resets `site.json` and `navigation.json` to defaults, and resets `JWT_SECRET` to a placeholder |
200
+ | `npm run fresh` | `reset` followed by `setup` - a clean install ready to use (it does not reseed; run `npm run seed` afterwards if you want the default content) |
201
+ | `npm run build` | Bundle admin JS with esbuild |
@@ -0,0 +1,260 @@
1
+ # Form Triggers
2
+
3
+ A **trigger** is attached to a field and does something to the *form* when the answers meet a
4
+ condition. "Are you over 18? No" ending the form there, saving what was answered and telling the
5
+ admins is one trigger.
6
+
7
+ It is the sibling of **Conditional Logic**, not a replacement for it:
8
+
9
+ | | Conditional Logic | Triggers |
10
+ |---|---|---|
11
+ | Decides | how one **field** behaves (shown, required, valid, what its options are) | what the **form** does (banners, toasts, other fields, the submit button) |
12
+ | Authored in | the field's ⚡ Conditional Logic panel | the field's 🎯 Triggers panel |
13
+ | Stored as | `field.logic` | `field.triggers[]` |
14
+
15
+ Both run on the same condition engine, so an operator behaves identically in either.
16
+
17
+ ---
18
+
19
+ ## Building one
20
+
21
+ In **Forms > edit a form**, open a field's **🎯 Triggers** panel and click **Add trigger**.
22
+
23
+ A trigger has three parts:
24
+
25
+ 1. **When** - one or more conditions, combined with *all of these are true* or *any of these is
26
+ true*. A condition can name **any** field on the form - the one the trigger hangs off is listed
27
+ first, marked *(this field)*, since "when this answer is No" is the usual case. That field is
28
+ also what "the rest of the form" is measured from.
29
+ 2. **Then** - what happens while (or when) the condition holds.
30
+ 3. **Otherwise** - optional; what happens while (or when) it does not.
31
+
32
+ ---
33
+
34
+ ## The two kinds of action
35
+
36
+ This is the part worth reading twice, because it decides how everything behaves.
37
+
38
+ **State actions apply *while* the condition holds and are reverted the moment it stops.** They are
39
+ re-evaluated on every keystroke, so they cannot drift out of step with the answers.
40
+
41
+ | Action | Effect |
42
+ |---|---|
43
+ | **Show a banner** | An inline message above the field, below it, or at the top of the form. Choose a level (info / success / warning / error) and whether the visitor can dismiss it. |
44
+ | **Hide fields** | Removes them from the form. A hidden field is never required and its value is not submitted. |
45
+ | **Disable fields** | Leaves them visible but unanswerable. Treated the same as hidden on submission - the visitor was given no way to answer. |
46
+ | **Make fields required** | Adds the requirement on top of whatever the field already had. Hiding a field beats requiring it. |
47
+ | **Block submission** | Refuses the submit and puts your reason under the button. |
48
+ | **End the form here** | Masks everything after this field, shows your message in its place, and turns the submit button (a wizard's *Next* included) into *Finish*. See [Ending a form early](#ending-a-form-early). |
49
+
50
+ **Event actions fire *once*, on the transition into that branch.** They are not undone, because an
51
+ un-fired toast is not a thing.
52
+
53
+ | Action | Effect |
54
+ |---|---|
55
+ | **Show a toast** | A transient corner message. |
56
+ | **Jump to a wizard step** | Moves a multi-page form to a step, counting from 0. |
57
+ | **Redirect after submit** | Sends the visitor to a URL once the submission is stored. Wins over the form's own success redirect. |
58
+ | **Celebrate** | Fires a celebration effect. Respects `prefers-reduced-motion`. |
59
+ | **Run a CMS action** | Runs an Actions artefact server-side, after the entry is stored. |
60
+ | **Notify the admins** | Raises a notification in the admin when the form is submitted - the bell, and a desktop notification for anyone who turned those on. See [Telling the admins](#telling-the-admins). |
61
+
62
+ Event actions do **not** fire on the initial render. A form that opens with an answer already in it
63
+ - a wizard step revisited, a pre-filled value - would otherwise greet the visitor with a toast about
64
+ a choice they have not just made. Tick **Only once** to fire the first time and never again.
65
+
66
+ Swinging an answer back and forth *does* re-fire, because the `then` and `otherwise` branches are
67
+ tracked separately. That is what "when you pick No" means.
68
+
69
+ ---
70
+
71
+ ## Ending a form early
72
+
73
+ Some answers mean there is nothing more to ask - an applicant who is under age, a region you do not
74
+ serve. **Block submission** refuses those outright, which also means nobody ever finds out they
75
+ happened. **End the form here** finishes the form instead:
76
+
77
+ - everything after the field is masked (removed from view), and your message takes its place
78
+ - the submit button - or a wizard's *Next* - reads *Finish* (or your own button text)
79
+ - *Finish* posts the answers given so far; the masked fields are neither required nor stored,
80
+ even where the form marks them required
81
+ - the visitor sees your closing message, or the form's success message if you left it blank
82
+
83
+ The field the trigger hangs off stays answerable. Change the answer and the rest of the form comes
84
+ back, exactly as it was.
85
+
86
+ The stored submission carries `meta.outcome`:
87
+
88
+ ```json
89
+ {"type": "ended", "trigger": "trg-1789806137396-2yeti:then", "field": "over18"}
90
+ ```
91
+
92
+ Untick **Save the answers given so far** to keep nothing: no submission is stored, and the form's
93
+ own email, webhook and action do not run - there is no submission for them to report. A **Notify
94
+ the admins** action on the same trigger still fires, so you still hear about it.
95
+
96
+ Untick **Let the visitor finish** to stop the form dead instead: the rest is still masked and your
97
+ message still shows, but the submit button (or a wizard's *Next*) is disabled and the server refuses
98
+ the post. Nothing is sent, so nothing is saved and **Notify the admins** cannot fire - use it when
99
+ the answer should simply go no further.
100
+
101
+ A **Block submission** in force beats an ending: a refused form is not finished.
102
+
103
+ ---
104
+
105
+ ## Telling the admins
106
+
107
+ **Notify the admins** raises a notification when the form is submitted with the condition holding -
108
+ the server checks it against the posted answers, so it cannot be faked or skipped. The notice names
109
+ the form, the question and the answer, and links to the submissions (or to the form, when nothing
110
+ was saved). Its level maps onto the bell's severities, with *Error* shown as *critical*.
111
+
112
+ Who receives it is a setting, not part of the form: **Notifications > settings**, source **Form
113
+ triggers**. It goes to every admin by default. At most 30 are raised an hour, so a busy form cannot
114
+ bury the inbox.
115
+
116
+ For an **email** instead (or as well), use **Run a CMS action** with an Action whose steps include
117
+ *Send an email*. Actions have a *Notify the admins* step too, for the same notice from anywhere an
118
+ Action runs.
119
+
120
+ ---
121
+
122
+ ## Putting answers in messages
123
+
124
+ A message can repeat what the visitor has answered. Write the field's name in double braces:
125
+
126
+ > Name *is not empty* -> **Show a banner**: `Hello {{name}}, thanks for getting in touch.`
127
+
128
+ The **Insert field** list beside each message box puts a token in at the cursor, so you do not need
129
+ to remember the names.
130
+
131
+ Tokens work in the messages the visitor sees: **Show a banner**, **Show a toast**, the reason under a
132
+ **Block submission**, and the message and closing message of **End the form here**. A banner changes
133
+ as the visitor types; a toast shows the answer at the moment it appears.
134
+
135
+ What a token shows:
136
+
137
+ - the answer as typed, on one line and cut off after 200 characters;
138
+ - for a dropdown, radio, chooser or checkbox group, the option's label rather than its stored value,
139
+ with several choices joined by commas;
140
+ - for a single tickbox, *Yes*, or nothing;
141
+ - nothing at all for a password, file or image field, for a field that is empty, for a name that is
142
+ not on the form, and for a field a trigger has hidden, disabled or ended the form before.
143
+
144
+ Answers are always shown as text: a visitor who types HTML into a field sees the characters, never
145
+ the markup. The server fills the same tokens from the same answers, so a blocked submission's `400`
146
+ and the closing message after an ending say exactly what the browser said.
147
+
148
+ **Redirect after submit** and **Notify the admins** do not fill tokens yet - a web address and an
149
+ admin notification need their own safety rules first.
150
+
151
+ Tokens refer to fields by name, and renaming a field does not update them (the same is true of
152
+ conditions). Saving warns about any token that will show as blank, so a rename is caught.
153
+
154
+ ---
155
+
156
+ ## Which fields an action addresses
157
+
158
+ Actions that act on other fields offer three targets:
159
+
160
+ | Target | Meaning |
161
+ |---|---|
162
+ | **The rest of the form** | Every field *after* this one, in form order |
163
+ | **Every other field** | Every field on the form except this one |
164
+ | **Chosen fields** | Exactly the fields you pick |
165
+
166
+ **The field the trigger hangs off is never a target**, whichever you choose. A trigger that disabled
167
+ its own field would freeze the form on the first wrong answer with no way back.
168
+
169
+ ---
170
+
171
+ ## It is enforced on the server too
172
+
173
+ Everything a trigger decides about *submission* is re-evaluated on the server, from the same engine,
174
+ when the form is posted:
175
+
176
+ - a **blocked** submit is refused with its message, whatever the browser was told
177
+ - **hidden** and **disabled** fields are neither required nor stored, even if a value is posted
178
+ - **required** fields added by a trigger are enforced
179
+ - an **ended** form is accepted with only the answers before the ending, and **notify** fires from
180
+ the server's own reading of the answers
181
+
182
+ Re-enabling the button in dev tools gets you a 400, not a submission. The browser-side copy exists to
183
+ answer immediately rather than after a round trip.
184
+
185
+ ---
186
+
187
+ ## Worked example: an age gate
188
+
189
+ On an "Are you over 18?" radio field:
190
+
191
+ - **When** `over18` (this field) equals `no`
192
+ - **Then**
193
+ - End the form here: *"Sorry - you must be 18 or over to apply."*, closing message *"Thanks for
194
+ your time."*
195
+ - Notify the admins, warning: *"Under-age applicant"*
196
+ - **Otherwise**
197
+ - Show a toast, success: *"Thanks - carry on."*
198
+
199
+ Answering *no* masks everything below and turns the button into *Finish*; finishing saves the
200
+ answer, thanks the visitor and puts a notice in the admins' bell. Answering *yes* brings the form
201
+ back and toasts once.
202
+
203
+ To refuse outright rather than record anything, use **Block submission** (with a banner and
204
+ **Disable fields** to show why) instead of ending the form.
205
+
206
+ ---
207
+
208
+ ## Stored shape
209
+
210
+ ```json
211
+ {
212
+ "name": "over18",
213
+ "type": "radio",
214
+ "options": ["yes", "no"],
215
+ "triggers": [
216
+ {
217
+ "id": "trg-1789806137396-2yeti",
218
+ "enabled": true,
219
+ "when": {"all": [{"field": "over18", "operator": "equals", "value": "no"}]},
220
+ "then": [
221
+ {"type": "end-form", "message": "Sorry - you must be 18 or over to apply.",
222
+ "finishLabel": "Finish", "doneMessage": "Thanks for your time."},
223
+ {"type": "notify", "message": "Under-age applicant", "level": "warning"}
224
+ ],
225
+ "otherwise": [
226
+ {"type": "toast", "message": "Thanks - carry on.", "level": "success"}
227
+ ]
228
+ }
229
+ ]
230
+ }
231
+ ```
232
+
233
+ `when` takes the same `{all: [...]}` / `{any: [...]}` condition groups conditional logic uses, with
234
+ the same operators, including the array semantics for checkbox groups and multi-select choosers -
235
+ a positive operator passes when **any** selected value matches, a negative when **none** does.
236
+
237
+ ---
238
+
239
+ ## Notes and limits
240
+
241
+ - A trigger with conditions but no actions is dropped on save rather than stored as an empty card.
242
+ - An unknown action type is ignored rather than breaking the form, so a record written by a newer
243
+ version degrades instead of failing.
244
+ - Two triggers redirecting at once is an authoring mistake, not a case the server resolves cleverly:
245
+ the first one wins.
246
+ - **Jump to a wizard step** needs a multi-page form; on a single-page form it does nothing.
247
+ - `end-form` always reaches the rest of the form; it takes no target. `record: false` turns saving
248
+ off, `finish: false` disables the submit altogether, and `finishLabel` / `doneMessage` are
249
+ optional.
250
+ - Only the first ending in force speaks - two panels saying "stop" would be one too many.
251
+ - Banners and toasts are the browser's business, so they leave no trace in the submission record.
252
+ What a trigger fired on is the answer it tested, and that answer is stored - read the decision back
253
+ from there.
254
+
255
+ ---
256
+
257
+ ## Related
258
+
259
+ - [Multi-Page Forms](multi-page-forms.md)
260
+ - [Configuration](../configuration.md)