domma-cms 1.6.60 → 1.7.0

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 (137) hide show
  1. package/CHANGELOG.md +4344 -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/page-editor-reference.js +5 -5
  8. package/admin/js/lib/shortcode-tags.js +1 -1
  9. package/admin/js/templates/docs/usage-shortcodes.html +39 -0
  10. package/docs/DommaFeatures.md +3005 -0
  11. package/docs/MultiTenant.md +176 -0
  12. package/docs/api-reference.md +1667 -0
  13. package/docs/cache.md +96 -0
  14. package/docs/configuration.md +1811 -0
  15. package/docs/editions-and-licences.md +190 -0
  16. package/docs/getting-started.md +201 -0
  17. package/docs/guides/form-triggers.md +260 -0
  18. package/docs/guides/mongodb-storage-adapter.md +282 -0
  19. package/docs/guides/multi-page-forms.md +121 -0
  20. package/docs/images/scribe-composer.png +0 -0
  21. package/docs/markdown-shortcodes.md +1738 -0
  22. package/docs/pentest-report-2026-04-03.md +181 -0
  23. package/docs/plans/2026-02-28-admin-topbar-login-forms.md +349 -0
  24. package/docs/plans/2026-02-28-domma-ui-polish.md +286 -0
  25. package/docs/plans/2026-02-28-reset-seed-fresh-commands.md +520 -0
  26. package/docs/plans/2026-03-02-cookie-consent-design.md +86 -0
  27. package/docs/plans/2026-03-02-cookie-consent-plugin.md +453 -0
  28. package/docs/plans/2026-03-02-tooltip-sweep-and-back-to-top-plugin-design.md +126 -0
  29. package/docs/plans/2026-03-02-tooltip-sweep-back-to-top.md +427 -0
  30. package/docs/plans/2026-03-05-cookie-consent-btt-core.md +115 -0
  31. package/docs/plans/2026-03-05-custom-css-migrate-to-core-design.md +35 -0
  32. package/docs/plans/2026-03-05-custom-css-migrate-to-core.md +352 -0
  33. package/docs/plans/2026-03-05-scribe-script-shortcode.md +373 -0
  34. package/docs/plans/2026-03-05-user-types-design.md +139 -0
  35. package/docs/plans/2026-03-05-user-types-implementation.md +1035 -0
  36. package/docs/plans/2026-03-09-page-editor-view-cta-inserts-design.md +78 -0
  37. package/docs/plans/2026-03-09-page-editor-view-cta-inserts.md +388 -0
  38. package/docs/plans/2026-03-09-pro-documentation-design.md +80 -0
  39. package/docs/plans/2026-03-09-pro-documentation.md +1017 -0
  40. package/docs/plans/2026-06-10-core-project-design.md +240 -0
  41. package/docs/plugin-development.md +827 -0
  42. package/docs/recruitment-recipe.md +501 -0
  43. package/docs/scaffolding.md +312 -0
  44. package/docs/screenshots/calculator-floating.png +0 -0
  45. package/docs/screenshots/calculator-standard.png +0 -0
  46. package/docs/screenshots/email-settings.png +0 -0
  47. package/docs/screenshots/messages-count.png +0 -0
  48. package/docs/structure/user-types.md +107 -0
  49. package/docs/superpowers/plans/2026-05-25-admin-sidebar-via-menus.md +1112 -0
  50. package/docs/superpowers/plans/2026-06-08-navbar-mobile-drawer-and-menu-enrichment.md +1161 -0
  51. package/docs/superpowers/plans/2026-06-25-domma-docs-project.md +695 -0
  52. package/docs/superpowers/plans/2026-06-26-surveys-HANDOFF.md +68 -0
  53. package/docs/superpowers/plans/2026-06-26-surveys-pro-plugin.md +1902 -0
  54. package/docs/superpowers/plans/2026-08-19-collection-context-sort-export.md +1577 -0
  55. package/docs/superpowers/plans/2026-10-09-content-api.md +1192 -0
  56. package/docs/superpowers/specs/2026-03-12-form-followup-actions-design.md +152 -0
  57. package/docs/superpowers/specs/2026-03-12-page-editor-form-insert-and-per-page-theme-design.md +115 -0
  58. package/docs/superpowers/specs/2026-03-17-nav-hidden-items-design.md +85 -0
  59. package/docs/superpowers/specs/2026-03-19-accordion-insert-design.md +175 -0
  60. package/docs/superpowers/specs/2026-03-25-static-block-shortcode-design.md +153 -0
  61. package/docs/superpowers/specs/2026-03-25-text-shortcode-design.md +168 -0
  62. package/docs/superpowers/specs/2026-04-05-card-builder-design.md +315 -0
  63. package/docs/superpowers/specs/2026-04-06-insert-builders-design.md +278 -0
  64. package/docs/superpowers/specs/2026-04-06-layouts-design.md +226 -0
  65. package/docs/superpowers/specs/2026-04-07-blog-plugin-design.md +300 -0
  66. package/docs/superpowers/specs/2026-04-07-calendar-plugin-design.md +538 -0
  67. package/docs/superpowers/specs/2026-04-17-components-area-design.md +368 -0
  68. package/docs/superpowers/specs/2026-05-02-effects-slideover-overhaul-design.md +193 -0
  69. package/docs/superpowers/specs/2026-05-06-dashboard-rebuild-design.md +257 -0
  70. package/docs/superpowers/specs/2026-05-24-menus-design.md +466 -0
  71. package/docs/superpowers/specs/2026-05-25-admin-sidebar-via-menus-design.md +358 -0
  72. package/docs/superpowers/specs/2026-05-25-projects-design.md +380 -0
  73. package/docs/superpowers/specs/2026-06-08-navbar-mobile-drawer-and-menu-enrichment-design.md +292 -0
  74. package/docs/superpowers/specs/2026-06-08-sidebar-tools-plugins-folders-design.md +59 -0
  75. package/docs/superpowers/specs/2026-06-25-domma-docs-project-design.md +192 -0
  76. package/docs/superpowers/specs/2026-06-26-domma-charts-upstream-proposal.md +44 -0
  77. package/docs/superpowers/specs/2026-06-26-manager-scheduler-upstream-proposal.md +46 -0
  78. package/docs/superpowers/specs/2026-06-26-surveys-pro-plugin-design.md +206 -0
  79. package/docs/superpowers/specs/2026-07-02-shortcode-context-menu-design.md +96 -0
  80. package/docs/superpowers/specs/2026-08-19-collection-context-sort-export-design.md +330 -0
  81. package/docs/superpowers/specs/2026-09-22-dcms-marketplace-design.md +1150 -0
  82. package/docs/superpowers/specs/2026-10-09-content-api-design.md +325 -0
  83. package/docs/superpowers/specs/plans/2026-03-12-form-followup-actions.md +624 -0
  84. package/docs/superpowers/specs/plans/2026-03-12-page-editor-form-insert-and-per-page-theme.md +125 -0
  85. package/docs/superpowers/specs/plans/2026-03-17-nav-hidden-items.md +578 -0
  86. package/docs/superpowers/specs/plans/2026-03-19-accordion-insert.md +635 -0
  87. package/docs/superpowers/specs/plans/2026-03-25-text-shortcode.md +545 -0
  88. package/docs/superpowers/specs/plans/2026-04-05-card-builder.md +1970 -0
  89. package/docs/superpowers/specs/plans/2026-04-06-insert-builders.md +1049 -0
  90. package/docs/superpowers/specs/plans/2026-04-06-layouts.md +1015 -0
  91. package/docs/superpowers/specs/plans/2026-04-07-calendar-plugin.md +1526 -0
  92. package/docs/superpowers/specs/plans/2026-04-08-plugin-monetisation-split.md +242 -0
  93. package/docs/superpowers/specs/plans/2026-04-17-components-area.md +2038 -0
  94. package/docs/superpowers/specs/plans/2026-05-02-effects-slideover-overhaul.md +2335 -0
  95. package/docs/superpowers/specs/plans/2026-05-06-dashboard-rebuild.md +1999 -0
  96. package/docs/superpowers/specs/plans/2026-05-17-cache-system.md +1436 -0
  97. package/docs/superpowers/specs/plans/2026-05-24-menus.md +3096 -0
  98. package/docs/superpowers/specs/plans/2026-05-25-projects.md +2869 -0
  99. package/docs/superpowers/specs/plans/2026-09-22-marketplace-step2-consolidation.md +505 -0
  100. package/docs/superpowers/specs/plans/2026-09-22-marketplace-step3-catalogue-and-key.md +154 -0
  101. package/docs/superpowers/specs/plans/2026-09-22-tools-promotion.md +260 -0
  102. package/docs/theming.md +320 -0
  103. package/package.json +2 -2
  104. package/public/js/celebrations/core/canvas.js +1 -1
  105. package/public/js/celebrations/index.js +1 -1
  106. package/public/js/celebrations/licenses/ABeeZee-Regular-OFL.txt +93 -0
  107. package/public/js/celebrations/licenses/Allura-Regular-OFL.txt +93 -0
  108. package/public/js/celebrations/message-attrs.mjs +1 -0
  109. package/public/js/celebrations/themes/anniversary.js +1 -0
  110. package/public/js/celebrations/themes/autumn.js +1 -0
  111. package/public/js/celebrations/themes/birthday.js +1 -0
  112. package/public/js/celebrations/themes/butterfly-flight.js +1 -0
  113. package/public/js/celebrations/themes/calendar.js +1 -0
  114. package/public/js/celebrations/themes/chinese-new-year-dates.js +1 -0
  115. package/public/js/celebrations/themes/chinese-new-year.js +1 -0
  116. package/public/js/celebrations/themes/christmas.js +1 -1
  117. package/public/js/celebrations/themes/easter.js +1 -0
  118. package/public/js/celebrations/themes/garden-drawing.js +1 -0
  119. package/public/js/celebrations/themes/garden.js +1 -0
  120. package/public/js/celebrations/themes/graduation.js +1 -0
  121. package/public/js/celebrations/themes/greeting.js +1 -0
  122. package/public/js/celebrations/themes/make-it-rain.js +1 -0
  123. package/public/js/celebrations/themes/money-rain.js +1 -0
  124. package/public/js/celebrations/themes/new-year.js +1 -0
  125. package/public/js/celebrations/themes/occasion-drawing.js +1 -0
  126. package/public/js/celebrations/themes/occasions.js +1 -0
  127. package/public/js/celebrations/themes/rain-control.js +1 -0
  128. package/public/js/celebrations/themes/sparkler-font-data.js +1 -0
  129. package/public/js/celebrations/themes/sparkler-font.js +1 -0
  130. package/public/js/celebrations/themes/sparkler-writing.js +1 -0
  131. package/public/js/celebrations/themes/summer-garden.js +1 -0
  132. package/public/js/celebrations/themes/winter.js +1 -0
  133. package/public/js/celebrations/trait-data.mjs +1 -1
  134. package/public/js/effects.js +1 -1
  135. package/scripts/build.js +4 -0
  136. package/server/services/markdown.js +5 -2
  137. package/server/templates/page.html +1 -1
@@ -0,0 +1,1017 @@
1
+ # Pro Documentation Implementation Plan
2
+
3
+ > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
4
+
5
+ **Goal:** Add a Pro documentation section - four public `/resources/pro/` pages (index, Views, Actions, CTA shortcode) plus a single tabbed "Pro Documentation" admin panel under `#/pro/docs`.
6
+
7
+ **Architecture:** Public pages are Markdown files following the existing resources pattern (hero + content + back link). The admin panel is a static HTML template with three tabs wired by a minimal JS view - mirrors the `documentationView` pattern exactly (templateUrl + onMount with icons + syntax scan).
8
+
9
+ **Tech Stack:** Markdown pages (Domma shortcodes), Domma admin SPA (templateUrl views, E.tabs, Domma.syntax.scan), sidebar-config.js, views/index.js, app.js routes.
10
+
11
+ ---
12
+
13
+ ## Task 1: Public - Pro section index page
14
+
15
+ **Files:**
16
+ - Create: `content/pages/resources/pro/index.md`
17
+
18
+ **Step 1: Create the Pro landing page**
19
+
20
+ ```markdown
21
+ ---
22
+ title: Pro Features
23
+ slug: pro
24
+ description: >-
25
+ Pro features for Domma CMS - Views, Actions, and CTA shortcodes.
26
+ Requires MongoDB.
27
+ layout: default
28
+ status: published
29
+ sortOrder: 20
30
+ showInNav: false
31
+ sidebar: false
32
+ seo:
33
+ title: Pro Features - Resources
34
+ description: Domma CMS Pro features reference
35
+ createdAt: '2026-03-09T00:00:00.000Z'
36
+ updatedAt: '2026-03-09T00:00:00.000Z'
37
+ tags: []
38
+ category: null
39
+ visibility: public
40
+ dconfig: null
41
+ ---
42
+
43
+ [hero variant="dark" size="sm" fullwidth="true" twinkle twinkle-count="20" blobs]
44
+
45
+ # Pro Features
46
+
47
+ Advanced features for Domma CMS requiring a MongoDB connection.
48
+
49
+ [/hero]
50
+
51
+ [badge style="warning"]Pro - requires MongoDB[/badge]
52
+
53
+ Pro features use MongoDB as a storage backend. A named connection must be configured in `config/connections.json` before creating Views or Actions.
54
+
55
+ [grid cols="3" gap="4"]
56
+ [col]
57
+ [card title="Views"]
58
+ MongoDB aggregation pipelines exposed as named, role-gated endpoints. Filter, join, sort, and reshape your collection data.
59
+
60
+ [Read more →](/resources/pro/views)
61
+ [/card]
62
+ [/col]
63
+ [col]
64
+ [card title="Actions"]
65
+ Multi-step operations on collection entries - update fields, send webhooks, fire emails, move or delete entries - triggered manually or via the `[cta]` shortcode.
66
+
67
+ [Read more →](/resources/pro/actions)
68
+ [/card]
69
+ [/col]
70
+ [col]
71
+ [card title="CTA Shortcode"]
72
+ Place action-trigger buttons anywhere in your Markdown content. Works standalone or integrated with the `[collection]` shortcode for per-entry buttons.
73
+
74
+ [Read more →](/resources/pro/cta)
75
+ [/card]
76
+ [/col]
77
+ [/grid]
78
+
79
+ ← [Back to Resources](/resources)
80
+ ```
81
+
82
+ **Step 2: Verify the page renders**
83
+
84
+ ```bash
85
+ curl -s http://localhost:4096/resources/pro | grep -c "Pro Features"
86
+ ```
87
+ Expected: `1` (or more)
88
+
89
+ **Step 3: Commit**
90
+
91
+ ```bash
92
+ git add content/pages/resources/pro/index.md
93
+ git commit -m "feat: add /resources/pro landing page"
94
+ ```
95
+
96
+ ---
97
+
98
+ ## Task 2: Public - Views reference page
99
+
100
+ **Files:**
101
+ - Create: `content/pages/resources/pro/views.md`
102
+
103
+ **Step 1: Create the Views page**
104
+
105
+ ```markdown
106
+ ---
107
+ title: Views
108
+ slug: views
109
+ description: >-
110
+ MongoDB aggregation pipeline Views - filter, join, and reshape collection
111
+ data with role-gated public endpoints.
112
+ layout: default
113
+ status: published
114
+ sortOrder: 21
115
+ showInNav: false
116
+ sidebar: false
117
+ seo:
118
+ title: Views - Pro Features
119
+ description: Domma CMS Views reference
120
+ createdAt: '2026-03-09T00:00:00.000Z'
121
+ updatedAt: '2026-03-09T00:00:00.000Z'
122
+ tags: []
123
+ category: null
124
+ visibility: public
125
+ dconfig: null
126
+ ---
127
+
128
+ [hero variant="dark" size="sm" fullwidth="true" twinkle twinkle-count="20" blobs]
129
+
130
+ # Views
131
+
132
+ [/hero]
133
+
134
+ [badge style="warning"]Pro - requires MongoDB[/badge]
135
+
136
+ A **View** is a saved MongoDB aggregation pipeline that runs against a collection and returns shaped results. Views are defined in the admin under **Data → Views** and exposed via a REST endpoint that respects role-level access and optional row-level filtering.
137
+
138
+ ---
139
+
140
+ ## Creating a View
141
+
142
+ Go to **Data → Views → New View** and fill in:
143
+
144
+ | Field | Description |
145
+ |-------|-------------|
146
+ | **Title** | Human-readable name shown in the admin |
147
+ | **Slug** | URL-safe identifier - auto-generated from the title |
148
+ | **Description** | Optional notes about what this View returns |
149
+ | **Source Collection** | The primary collection the pipeline runs against |
150
+ | **Connection** | MongoDB connection name from `config/connections.json` (default: `default`) |
151
+
152
+ ---
153
+
154
+ ## Pipeline Stages
155
+
156
+ Switch to the **Pipeline** tab to add aggregation stages. Each stage is a JSON object using standard MongoDB aggregation syntax.
157
+
158
+ ### Allowed stages
159
+
160
+ | Stage | Purpose |
161
+ |-------|---------|
162
+ | `$match` | Filter documents by field values |
163
+ | `$sort` | Order results by one or more fields |
164
+ | `$project` | Include, exclude, or rename fields |
165
+ | `$lookup` | Join data from another collection |
166
+ | `$unwind` | Flatten an array field into separate documents |
167
+ | `$addFields` | Compute and add new fields |
168
+ | `$group` | Aggregate documents (count, sum, etc.) |
169
+ | `$limit` | Cap the number of results |
170
+ | `$skip` | Skip N results (useful for manual pagination) |
171
+ | `$count` | Return a document count |
172
+
173
+ Stages `$out`, `$merge`, `$function`, `$accumulator`, and `$graphLookup` are **blocked** for security.
174
+
175
+ ### Collection naming
176
+
177
+ The pipeline always runs on the MongoDB collection `cms_{slug}` - e.g. the `feedback` collection is stored as `cms_feedback`. Use this prefix when writing `$lookup` joins.
178
+
179
+ ### Example pipeline - active users with submission count
180
+
181
+ ```json
182
+ [
183
+ { "$match": { "data.isActive": true } },
184
+ {
185
+ "$lookup": {
186
+ "from": "cms_feedback",
187
+ "localField": "_id",
188
+ "foreignField": "data.userId",
189
+ "as": "submissions"
190
+ }
191
+ },
192
+ {
193
+ "$addFields": {
194
+ "submissionCount": { "$size": "$submissions" }
195
+ }
196
+ },
197
+ { "$project": { "data.name": 1, "data.email": 1, "submissionCount": 1 } },
198
+ { "$sort": { "submissionCount": -1 } }
199
+ ]
200
+ ```
201
+
202
+ ---
203
+
204
+ ## Display Settings
205
+
206
+ The **Display** tab controls how results appear in the admin preview and public endpoint:
207
+
208
+ | Field | Description |
209
+ |-------|-------------|
210
+ | **Display Mode** | `table` (default) or `list` |
211
+ | **Page Size** | Rows per page in the table (default 25) |
212
+ | **Column Definitions** | JSON array: `[{"key":"data.name","label":"Name"}]` - `key` is dot-notation path into each result document |
213
+
214
+ ---
215
+
216
+ ## Access Control
217
+
218
+ The **Access** tab controls who can call this View:
219
+
220
+ - **Allowed Roles** - tick which roles can call `GET /api/views/:slug/public`
221
+ - **Public** - when checked, no authentication is required at all
222
+ - **Row-Level Access** - when enabled, each user only sees entries they own or are assigned to (admins always see everything)
223
+
224
+ ### Row-level modes
225
+
226
+ | Mode | Behaviour |
227
+ |------|-----------|
228
+ | **Owner** | Only entries whose `meta.createdBy` matches the current user |
229
+ | **Field Match** | A specified field on the entry must match a property of the current user (e.g. `assigned_to` = `user.id`) |
230
+
231
+ ---
232
+
233
+ ## Endpoints
234
+
235
+ | Method | URL | Auth |
236
+ |--------|-----|------|
237
+ | `GET` | `/api/views` | Admin / manager |
238
+ | `POST` | `/api/views` | Admin / manager |
239
+ | `GET` | `/api/views/:slug` | Admin / manager |
240
+ | `PUT` | `/api/views/:slug` | Admin / manager |
241
+ | `DELETE` | `/api/views/:slug` | Admin / manager |
242
+ | `GET` | `/api/views/:slug/execute` | Admin (preview) |
243
+ | `GET` | `/api/views/:slug/public` | Role-gated (see Access tab) |
244
+
245
+ ---
246
+
247
+ ← [Back to Pro Features](/resources/pro)
248
+ ```
249
+
250
+ **Step 2: Verify**
251
+
252
+ ```bash
253
+ curl -s http://localhost:4096/resources/pro/views | grep -c "aggregation"
254
+ ```
255
+ Expected: `1` (or more)
256
+
257
+ **Step 3: Commit**
258
+
259
+ ```bash
260
+ git add content/pages/resources/pro/views.md
261
+ git commit -m "feat: add /resources/pro/views reference page"
262
+ ```
263
+
264
+ ---
265
+
266
+ ## Task 3: Public - Actions reference page
267
+
268
+ **Files:**
269
+ - Create: `content/pages/resources/pro/actions.md`
270
+
271
+ **Step 1: Create the Actions page**
272
+
273
+ ```markdown
274
+ ---
275
+ title: Actions
276
+ slug: actions
277
+ description: >-
278
+ Multi-step Actions on collection entries - update fields, send webhooks,
279
+ fire emails, and more.
280
+ layout: default
281
+ status: published
282
+ sortOrder: 22
283
+ showInNav: false
284
+ sidebar: false
285
+ seo:
286
+ title: Actions - Pro Features
287
+ description: Domma CMS Actions reference
288
+ createdAt: '2026-03-09T00:00:00.000Z'
289
+ updatedAt: '2026-03-09T00:00:00.000Z'
290
+ tags: []
291
+ category: null
292
+ visibility: public
293
+ dconfig: null
294
+ ---
295
+
296
+ [hero variant="dark" size="sm" fullwidth="true" twinkle twinkle-count="20" blobs]
297
+
298
+ # Actions
299
+
300
+ [/hero]
301
+
302
+ [badge style="warning"]Pro - requires MongoDB[/badge]
303
+
304
+ An **Action** is a named sequence of steps that runs against a single collection entry. Actions are defined in the admin under **Data → Actions** and can be triggered manually from the entry list, or from any public page via the `[cta]` shortcode.
305
+
306
+ ---
307
+
308
+ ## Creating an Action
309
+
310
+ Go to **Data → Actions → New Action** and fill in:
311
+
312
+ | Field | Description |
313
+ |-------|-------------|
314
+ | **Title** | Human-readable name (e.g. *Approve Application*) |
315
+ | **Slug** | URL-safe identifier - auto-generated from the title |
316
+ | **Description** | Optional notes |
317
+ | **Target Collection** | The collection this action operates on |
318
+
319
+ ---
320
+
321
+ ## Trigger Settings
322
+
323
+ The **Trigger** tab controls how the Action is invoked from the admin:
324
+
325
+ | Field | Description |
326
+ |-------|-------------|
327
+ | **Trigger Type** | Currently: `Manual` (button in the entry list) |
328
+ | **Button Label** | Label shown on the trigger button (default: `Run`) |
329
+ | **Button Icon** | Domma icon name (e.g. `check-circle`, `zap`, `send`) |
330
+ | **Confirmation Message** | Optional prompt before execution - leave blank to skip |
331
+
332
+ ---
333
+
334
+ ## Steps
335
+
336
+ The **Steps** tab defines what the Action does. Steps run in order. If a step fails, execution stops and a partial result is returned indicating how many steps completed.
337
+
338
+ ### Step types
339
+
340
+ #### `updateField`
341
+
342
+ Sets a field on the entry to a new value. Supports template variables.
343
+
344
+ ```json
345
+ {
346
+ "field": "status",
347
+ "value": "approved"
348
+ }
349
+ ```
350
+
351
+ #### `deleteEntry`
352
+
353
+ Permanently deletes the target entry. No additional config needed.
354
+
355
+ #### `moveToCollection`
356
+
357
+ Moves the entry to a different collection (copies data, then deletes from source).
358
+
359
+ ```json
360
+ {
361
+ "targetCollection": "approved-applications"
362
+ }
363
+ ```
364
+
365
+ #### `webhook`
366
+
367
+ POSTs the entry data to an external URL.
368
+
369
+ ```json
370
+ {
371
+ "url": "https://hooks.example.com/notify",
372
+ "headers": { "X-Secret": "{{env.CMS_PUBLIC_HOOK_SECRET}}" }
373
+ }
374
+ ```
375
+
376
+ #### `email`
377
+
378
+ Sends an email via the configured SMTP server (set in **Settings → Email / SMTP**).
379
+
380
+ ```json
381
+ {
382
+ "to": "{{entry.data.email}}",
383
+ "subject": "Your application was approved",
384
+ "body": "Hi {{entry.data.name}},\n\nYour application has been approved."
385
+ }
386
+ ```
387
+
388
+ ---
389
+
390
+ ## Template Variables
391
+
392
+ All step field values support template interpolation using `{{...}}` syntax:
393
+
394
+ | Variable | Value |
395
+ |----------|-------|
396
+ | `{{entry.data.fieldName}}` | Any field from the target entry |
397
+ | `{{entry.id}}` | The entry's UUID |
398
+ | `{{now}}` | Current timestamp in ISO 8601 format |
399
+ | `{{user.name}}` | Name of the user who triggered the Action |
400
+ | `{{user.email}}` | Email of the triggering user |
401
+ | `{{user.id}}` | UUID of the triggering user |
402
+ | `{{env.CMS_PUBLIC_*}}` | Public environment variables (prefixed `CMS_PUBLIC_`) |
403
+
404
+ ---
405
+
406
+ ## Access Control
407
+
408
+ The **Access** tab works identically to Views:
409
+
410
+ - **Allowed Roles** - who can call `POST /api/actions/:slug/public`
411
+ - **Row-Level Access** - restrict execution to entries owned by or assigned to the current user
412
+
413
+ ---
414
+
415
+ ## Endpoints
416
+
417
+ | Method | URL | Auth |
418
+ |--------|-----|------|
419
+ | `GET` | `/api/actions` | Admin / manager |
420
+ | `POST` | `/api/actions` | Admin / manager |
421
+ | `GET` | `/api/actions/:slug` | Admin / manager |
422
+ | `PUT` | `/api/actions/:slug` | Admin / manager |
423
+ | `DELETE` | `/api/actions/:slug` | Admin / manager |
424
+ | `POST` | `/api/actions/:slug/execute` | Admin (test run) |
425
+ | `POST` | `/api/actions/:slug/public` | Role-gated (see Access tab) |
426
+
427
+ The public endpoint expects a JSON body: `{ "entryId": "uuid-of-entry" }`
428
+
429
+ ---
430
+
431
+ ← [Back to Pro Features](/resources/pro)
432
+ ```
433
+
434
+ **Step 2: Verify**
435
+
436
+ ```bash
437
+ curl -s http://localhost:4096/resources/pro/actions | grep -c "updateField"
438
+ ```
439
+ Expected: `1` (or more)
440
+
441
+ **Step 3: Commit**
442
+
443
+ ```bash
444
+ git add content/pages/resources/pro/actions.md
445
+ git commit -m "feat: add /resources/pro/actions reference page"
446
+ ```
447
+
448
+ ---
449
+
450
+ ## Task 4: Public - CTA shortcode reference page
451
+
452
+ **Files:**
453
+ - Create: `content/pages/resources/pro/cta.md`
454
+
455
+ **Step 1: Create the CTA page**
456
+
457
+ ```markdown
458
+ ---
459
+ title: CTA Shortcode
460
+ slug: cta
461
+ description: >-
462
+ Place Action-trigger buttons anywhere in your Markdown content using the
463
+ [cta] shortcode.
464
+ layout: default
465
+ status: published
466
+ sortOrder: 23
467
+ showInNav: false
468
+ sidebar: false
469
+ seo:
470
+ title: CTA Shortcode - Pro Features
471
+ description: Domma CMS CTA shortcode reference
472
+ createdAt: '2026-03-09T00:00:00.000Z'
473
+ updatedAt: '2026-03-09T00:00:00.000Z'
474
+ tags: []
475
+ category: null
476
+ visibility: public
477
+ dconfig: null
478
+ ---
479
+
480
+ [hero variant="dark" size="sm" fullwidth="true" twinkle twinkle-count="20" blobs]
481
+
482
+ # CTA Shortcode
483
+
484
+ [/hero]
485
+
486
+ The `[cta]` shortcode renders a button that triggers a named Action against a specific entry. The button uses the logged-in user's JWT to authenticate the request - no separate login is required if the user is already signed in to the admin.
487
+
488
+ ---
489
+
490
+ ## Syntax
491
+
492
+ Two forms are supported:
493
+
494
+ **Wrapping form** - button label comes from the body:
495
+
496
+ ```
497
+ [cta action="slug" entry="entry-id"]Button label[/cta]
498
+ ```
499
+
500
+ **Self-closing form** - button label from `label` attribute:
501
+
502
+ ```
503
+ [cta action="slug" entry="entry-id" label="Button label" /]
504
+ ```
505
+
506
+ ---
507
+
508
+ ## Attributes
509
+
510
+ | Attribute | Required | Default | Description |
511
+ |-----------|----------|---------|-------------|
512
+ | `action` | Yes | - | Slug of the Action to execute |
513
+ | `entry` | Yes | - | UUID of the entry to act on |
514
+ | `label` | No | `"Run"` | Button text (self-closing form only) |
515
+ | `style` | No | `"primary"` | Button variant: `primary`, `secondary`, `ghost`, `danger` |
516
+ | `icon` | No | - | Domma icon name shown before the label |
517
+ | `size` | No | - | Button size: `sm`, `md`, `lg` |
518
+ | `confirm` | No | - | Confirmation prompt text - shown before executing |
519
+
520
+ ---
521
+
522
+ ## Examples
523
+
524
+ ### Basic button
525
+
526
+ ```
527
+ [cta action="approve-application" entry="abc-123"]Approve[/cta]
528
+ ```
529
+
530
+ ### With icon and confirmation
531
+
532
+ ```
533
+ [cta action="approve-application" entry="abc-123" icon="check" style="primary" confirm="Approve this application?"]Approve[/cta]
534
+ ```
535
+
536
+ ### Danger button with confirmation
537
+
538
+ ```
539
+ [cta action="delete-entry" entry="abc-123" style="danger" confirm="Permanently delete this entry?"]Delete[/cta]
540
+ ```
541
+
542
+ ### Self-closing form
543
+
544
+ ```
545
+ [cta action="send-welcome-email" entry="abc-123" label="Send welcome email" icon="send" /]
546
+ ```
547
+
548
+ ---
549
+
550
+ ## Collection Integration
551
+
552
+ Add per-entry CTA buttons to any `[collection]` shortcode by adding `cta` and related attributes:
553
+
554
+ ```
555
+ [collection slug="applications" display="cards" title-field="name"
556
+ cta="approve-application"
557
+ cta-label="Approve"
558
+ cta-icon="check"
559
+ cta-style="primary"
560
+ cta-confirm="Approve this application?" /]
561
+ ```
562
+
563
+ ### Collection CTA attributes
564
+
565
+ | Attribute | Default | Description |
566
+ |-----------|---------|-------------|
567
+ | `cta` | - | Action slug - enables per-entry buttons |
568
+ | `cta-label` | `"Run"` | Button label |
569
+ | `cta-icon` | - | Domma icon name |
570
+ | `cta-style` | `"primary"` | Button variant |
571
+ | `cta-confirm` | - | Confirmation prompt |
572
+
573
+ All three display modes support CTA buttons: **cards** (footer), **list** (inline), and **table** (dedicated column).
574
+
575
+ ---
576
+
577
+ ## Authentication
578
+
579
+ The button reads the user's token from `S.get('auth_token')` - the same token used by the admin panel. If the user is not logged in, clicking the button shows a warning toast:
580
+
581
+ > *"Please log in to perform this action."*
582
+
583
+ The Action's **Access** tab controls which roles are allowed to trigger it via the public endpoint.
584
+
585
+ ---
586
+
587
+ ← [Back to Pro Features](/resources/pro)
588
+ ```
589
+
590
+ **Step 2: Verify**
591
+
592
+ ```bash
593
+ curl -s http://localhost:4096/resources/pro/cta | grep -c "cta-label"
594
+ ```
595
+ Expected: `1` (or more)
596
+
597
+ **Step 3: Commit**
598
+
599
+ ```bash
600
+ git add content/pages/resources/pro/cta.md
601
+ git commit -m "feat: add /resources/pro/cta shortcode reference page"
602
+ ```
603
+
604
+ ---
605
+
606
+ ## Task 5: Update Resources index - add Pro card
607
+
608
+ **Files:**
609
+ - Modify: `content/pages/resources/index.md`
610
+
611
+ **Step 1: Add a Pro Features card to the grid**
612
+
613
+ In `content/pages/resources/index.md`, add a new `[col]` + `[card]` block inside the existing `[grid cols="3" gap="4"]` - after the last card (Dependencies) and before `[/grid]`:
614
+
615
+ ```
616
+ [col]
617
+ [card title="Pro Features"]
618
+ Views, Actions, and the CTA shortcode - advanced features powered by MongoDB. [badge style="warning"]Pro[/badge]
619
+
620
+ [Read more →](/resources/pro)
621
+ [/card]
622
+ [/col]
623
+ ```
624
+
625
+ **Step 2: Verify the Resources index still renders**
626
+
627
+ ```bash
628
+ curl -s http://localhost:4096/resources | grep -c "Pro Features"
629
+ ```
630
+ Expected: `1`
631
+
632
+ **Step 3: Commit**
633
+
634
+ ```bash
635
+ git add content/pages/resources/index.md
636
+ git commit -m "feat: add Pro Features card to resources index"
637
+ ```
638
+
639
+ ---
640
+
641
+ ## Task 6: Admin - Pro Documentation view JS + HTML template
642
+
643
+ **Files:**
644
+ - Create: `admin/js/views/pro-docs.js`
645
+ - Create: `admin/js/templates/pro-docs.html`
646
+
647
+ **Step 1: Create the view module**
648
+
649
+ `admin/js/views/pro-docs.js`:
650
+
651
+ ```js
652
+ /**
653
+ * Pro Documentation View
654
+ * Reference for Pro-only features: Views, Actions, and the CTA shortcode.
655
+ */
656
+ export const proDocsView = {
657
+ templateUrl: '/admin/js/templates/pro-docs.html',
658
+
659
+ async onMount($container) {
660
+ E.tabs($container.find('#pro-docs-tabs').get(0));
661
+ Domma.icons.scan();
662
+ Domma.syntax.scan();
663
+ }
664
+ };
665
+ ```
666
+
667
+ **Step 2: Create the template**
668
+
669
+ `admin/js/templates/pro-docs.html` - a three-tab layout (Views, Actions, CTA Shortcode). Each tab is a collapsible-card reference section matching the style of `documentation.html`.
670
+
671
+ ```html
672
+ <div class="view-header">
673
+ <h1><span data-icon="zap"></span> Pro Documentation</h1>
674
+ </div>
675
+
676
+ <div class="tabs" id="pro-docs-tabs">
677
+ <div class="tab-list">
678
+ <button class="tab-item active">Views</button>
679
+ <button class="tab-item">Actions</button>
680
+ <button class="tab-item">CTA Shortcode</button>
681
+ </div>
682
+ <div class="tab-content">
683
+
684
+ <!-- ── Views tab ─────────────────────────────────────── -->
685
+ <div class="tab-panel active">
686
+
687
+ <div class="card card-collapsible mb-4">
688
+ <div class="card-header" role="button" tabindex="0">
689
+ <div class="card-header-content"><h2><span data-icon="eye"></span> What is a View?</h2></div>
690
+ <span class="card-collapse-icon" data-icon="chevron-down"></span>
691
+ </div>
692
+ <div class="card-body docs-body">
693
+ <p>A <strong>View</strong> is a saved MongoDB aggregation pipeline that runs against a collection and returns shaped results. Views are created under <strong>Data → Views</strong> and exposed via a REST endpoint that respects role-level and row-level access.</p>
694
+ <p>Views require a MongoDB connection configured in <code>config/connections.json</code>.</p>
695
+ </div>
696
+ </div>
697
+
698
+ <div class="card card-collapsible mb-4">
699
+ <div class="card-header" role="button" tabindex="0">
700
+ <div class="card-header-content"><h2><span data-icon="layers"></span> Allowed Pipeline Stages</h2></div>
701
+ <span class="card-collapse-icon" data-icon="chevron-down"></span>
702
+ </div>
703
+ <div class="card-body docs-body">
704
+ <table class="table table-sm">
705
+ <thead><tr><th>Stage</th><th>Purpose</th></tr></thead>
706
+ <tbody>
707
+ <tr><td><code>$match</code></td><td>Filter documents by field values</td></tr>
708
+ <tr><td><code>$sort</code></td><td>Order results</td></tr>
709
+ <tr><td><code>$project</code></td><td>Include, exclude, or rename fields</td></tr>
710
+ <tr><td><code>$lookup</code></td><td>Join from another collection</td></tr>
711
+ <tr><td><code>$unwind</code></td><td>Flatten an array field</td></tr>
712
+ <tr><td><code>$addFields</code></td><td>Compute new fields</td></tr>
713
+ <tr><td><code>$group</code></td><td>Aggregate (count, sum, etc.)</td></tr>
714
+ <tr><td><code>$limit</code></td><td>Cap results</td></tr>
715
+ <tr><td><code>$skip</code></td><td>Skip N results</td></tr>
716
+ <tr><td><code>$count</code></td><td>Return a document count</td></tr>
717
+ </tbody>
718
+ </table>
719
+ <p class="text-muted" style="margin-top:.75rem;">Blocked: <code>$out</code>, <code>$merge</code>, <code>$function</code>, <code>$accumulator</code>, <code>$graphLookup</code></p>
720
+ <p>Collections are prefixed <code>cms_</code> in MongoDB - use this prefix in <code>$lookup</code> <code>from</code> values.</p>
721
+ </div>
722
+ </div>
723
+
724
+ <div class="card card-collapsible mb-4">
725
+ <div class="card-header" role="button" tabindex="0">
726
+ <div class="card-header-content"><h2><span data-icon="code"></span> Example Pipeline</h2></div>
727
+ <span class="card-collapse-icon" data-icon="chevron-down"></span>
728
+ </div>
729
+ <div class="card-body docs-body">
730
+ <p>Match active entries and count related submissions:</p>
731
+ <pre class="code-block"><code>[
732
+ { "$match": { "data.isActive": true } },
733
+ {
734
+ "$lookup": {
735
+ "from": "cms_feedback",
736
+ "localField": "_id",
737
+ "foreignField": "data.userId",
738
+ "as": "submissions"
739
+ }
740
+ },
741
+ { "$addFields": { "submissionCount": { "$size": "$submissions" } } },
742
+ { "$project": { "data.name": 1, "data.email": 1, "submissionCount": 1 } },
743
+ { "$sort": { "submissionCount": -1 } }
744
+ ]</code></pre>
745
+ </div>
746
+ </div>
747
+
748
+ <div class="card card-collapsible mb-4">
749
+ <div class="card-header" role="button" tabindex="0">
750
+ <div class="card-header-content"><h2><span data-icon="lock"></span> Access Control</h2></div>
751
+ <span class="card-collapse-icon" data-icon="chevron-down"></span>
752
+ </div>
753
+ <div class="card-body docs-body">
754
+ <table class="table table-sm">
755
+ <thead><tr><th>Setting</th><th>Description</th></tr></thead>
756
+ <tbody>
757
+ <tr><td>Allowed Roles</td><td>Which roles can call <code>GET /api/views/:slug/public</code></td></tr>
758
+ <tr><td>Public</td><td>No authentication required when checked</td></tr>
759
+ <tr><td>Row-Level - Owner</td><td>User sees only entries they created</td></tr>
760
+ <tr><td>Row-Level - Field Match</td><td>A specified entry field must match a user property</td></tr>
761
+ </tbody>
762
+ </table>
763
+ </div>
764
+ </div>
765
+
766
+ </div><!-- /Views tab -->
767
+
768
+ <!-- ── Actions tab ───────────────────────────────────── -->
769
+ <div class="tab-panel">
770
+
771
+ <div class="card card-collapsible mb-4">
772
+ <div class="card-header" role="button" tabindex="0">
773
+ <div class="card-header-content"><h2><span data-icon="zap"></span> What is an Action?</h2></div>
774
+ <span class="card-collapse-icon" data-icon="chevron-down"></span>
775
+ </div>
776
+ <div class="card-body docs-body">
777
+ <p>An <strong>Action</strong> is a named sequence of steps that runs against a single collection entry. Actions are defined under <strong>Data → Actions</strong> and can be triggered from the entry list or via the <code>[cta]</code> shortcode on any public page.</p>
778
+ <p>Actions require a MongoDB connection configured in <code>config/connections.json</code>.</p>
779
+ <p>Steps run in order. If a step fails, execution stops and a partial result is returned with a <code>stepsCompleted</code> count.</p>
780
+ </div>
781
+ </div>
782
+
783
+ <div class="card card-collapsible mb-4">
784
+ <div class="card-header" role="button" tabindex="0">
785
+ <div class="card-header-content"><h2><span data-icon="list"></span> Step Types</h2></div>
786
+ <span class="card-collapse-icon" data-icon="chevron-down"></span>
787
+ </div>
788
+ <div class="card-body docs-body">
789
+ <table class="table table-sm">
790
+ <thead><tr><th>Type</th><th>What it does</th></tr></thead>
791
+ <tbody>
792
+ <tr><td><code>updateField</code></td><td>Sets a field on the entry to a new value</td></tr>
793
+ <tr><td><code>deleteEntry</code></td><td>Permanently deletes the target entry</td></tr>
794
+ <tr><td><code>moveToCollection</code></td><td>Moves the entry to a different collection</td></tr>
795
+ <tr><td><code>webhook</code></td><td>POSTs entry data to an external URL</td></tr>
796
+ <tr><td><code>email</code></td><td>Sends an email via the configured SMTP server</td></tr>
797
+ </tbody>
798
+ </table>
799
+ </div>
800
+ </div>
801
+
802
+ <div class="card card-collapsible mb-4">
803
+ <div class="card-header" role="button" tabindex="0">
804
+ <div class="card-header-content"><h2><span data-icon="tag"></span> Template Variables</h2></div>
805
+ <span class="card-collapse-icon" data-icon="chevron-down"></span>
806
+ </div>
807
+ <div class="card-body docs-body">
808
+ <p>All step field values support <code>&#123;&#123;...&#125;&#125;</code> interpolation:</p>
809
+ <table class="table table-sm">
810
+ <thead><tr><th>Variable</th><th>Value</th></tr></thead>
811
+ <tbody>
812
+ <tr><td><code>&#123;&#123;entry.data.fieldName&#125;&#125;</code></td><td>Any field from the target entry</td></tr>
813
+ <tr><td><code>&#123;&#123;entry.id&#125;&#125;</code></td><td>The entry's UUID</td></tr>
814
+ <tr><td><code>&#123;&#123;now&#125;&#125;</code></td><td>Current ISO 8601 timestamp</td></tr>
815
+ <tr><td><code>&#123;&#123;user.name&#125;&#125;</code></td><td>Name of the triggering user</td></tr>
816
+ <tr><td><code>&#123;&#123;user.email&#125;&#125;</code></td><td>Email of the triggering user</td></tr>
817
+ <tr><td><code>&#123;&#123;user.id&#125;&#125;</code></td><td>UUID of the triggering user</td></tr>
818
+ <tr><td><code>&#123;&#123;env.CMS_PUBLIC_*&#125;&#125;</code></td><td>Public environment variables</td></tr>
819
+ </tbody>
820
+ </table>
821
+ </div>
822
+ </div>
823
+
824
+ <div class="card card-collapsible mb-4">
825
+ <div class="card-header" role="button" tabindex="0">
826
+ <div class="card-header-content"><h2><span data-icon="code"></span> Step Examples</h2></div>
827
+ <span class="card-collapse-icon" data-icon="chevron-down"></span>
828
+ </div>
829
+ <div class="card-body docs-body">
830
+ <p><strong>updateField</strong> - mark an entry as approved:</p>
831
+ <pre class="code-block"><code>{ "field": "status", "value": "approved" }</code></pre>
832
+ <p><strong>webhook</strong> - notify an external service:</p>
833
+ <pre class="code-block"><code>{
834
+ "url": "https://hooks.example.com/notify",
835
+ "headers": { "X-Secret": "{{env.CMS_PUBLIC_HOOK_SECRET}}" }
836
+ }</code></pre>
837
+ <p><strong>email</strong> - send confirmation to applicant:</p>
838
+ <pre class="code-block"><code>{
839
+ "to": "{{entry.data.email}}",
840
+ "subject": "Your application was approved",
841
+ "body": "Hi {{entry.data.name}}, your application has been approved."
842
+ }</code></pre>
843
+ </div>
844
+ </div>
845
+
846
+ </div><!-- /Actions tab -->
847
+
848
+ <!-- ── CTA Shortcode tab ──────────────────────────────── -->
849
+ <div class="tab-panel">
850
+
851
+ <div class="card card-collapsible mb-4">
852
+ <div class="card-header" role="button" tabindex="0">
853
+ <div class="card-header-content"><h2><span data-icon="mouse-pointer"></span> What is the CTA shortcode?</h2></div>
854
+ <span class="card-collapse-icon" data-icon="chevron-down"></span>
855
+ </div>
856
+ <div class="card-body docs-body">
857
+ <p>The <code>[cta]</code> shortcode places an action-trigger button in any public page. Clicking it calls <code>POST /api/actions/:slug/public</code> with the entry ID, using the logged-in user's JWT.</p>
858
+ <p>If the user is not logged in, a warning toast is shown instead.</p>
859
+ </div>
860
+ </div>
861
+
862
+ <div class="card card-collapsible mb-4">
863
+ <div class="card-header" role="button" tabindex="0">
864
+ <div class="card-header-content"><h2><span data-icon="code"></span> Syntax &amp; Attributes</h2></div>
865
+ <span class="card-collapse-icon" data-icon="chevron-down"></span>
866
+ </div>
867
+ <div class="card-body docs-body">
868
+ <p><strong>Wrapping form:</strong></p>
869
+ <pre class="code-block"><code>[cta action="slug" entry="entry-id" icon="check" confirm="Are you sure?"]Button label[/cta]</code></pre>
870
+ <p><strong>Self-closing form:</strong></p>
871
+ <pre class="code-block"><code>[cta action="slug" entry="entry-id" label="Button label" /]</code></pre>
872
+ <table class="table table-sm" style="margin-top:1rem;">
873
+ <thead><tr><th>Attribute</th><th>Required</th><th>Default</th><th>Description</th></tr></thead>
874
+ <tbody>
875
+ <tr><td><code>action</code></td><td>Yes</td><td>-</td><td>Action slug</td></tr>
876
+ <tr><td><code>entry</code></td><td>Yes</td><td>-</td><td>Entry UUID to act on</td></tr>
877
+ <tr><td><code>label</code></td><td>No</td><td><code>"Run"</code></td><td>Button text (self-closing only)</td></tr>
878
+ <tr><td><code>style</code></td><td>No</td><td><code>"primary"</code></td><td>primary · secondary · ghost · danger</td></tr>
879
+ <tr><td><code>icon</code></td><td>No</td><td>-</td><td>Domma icon name</td></tr>
880
+ <tr><td><code>size</code></td><td>No</td><td>-</td><td>sm · md · lg</td></tr>
881
+ <tr><td><code>confirm</code></td><td>No</td><td>-</td><td>Confirmation prompt before executing</td></tr>
882
+ </tbody>
883
+ </table>
884
+ </div>
885
+ </div>
886
+
887
+ <div class="card card-collapsible mb-4">
888
+ <div class="card-header" role="button" tabindex="0">
889
+ <div class="card-header-content"><h2><span data-icon="grid"></span> Collection Integration</h2></div>
890
+ <span class="card-collapse-icon" data-icon="chevron-down"></span>
891
+ </div>
892
+ <div class="card-body docs-body">
893
+ <p>Add per-entry buttons to any <code>[collection]</code> shortcode:</p>
894
+ <pre class="code-block"><code>[collection slug="applications" display="cards" title-field="name"
895
+ cta="approve-application"
896
+ cta-label="Approve"
897
+ cta-icon="check"
898
+ cta-style="primary"
899
+ cta-confirm="Approve this application?" /]</code></pre>
900
+ <table class="table table-sm" style="margin-top:1rem;">
901
+ <thead><tr><th>Attribute</th><th>Default</th><th>Description</th></tr></thead>
902
+ <tbody>
903
+ <tr><td><code>cta</code></td><td>-</td><td>Action slug - enables per-entry buttons</td></tr>
904
+ <tr><td><code>cta-label</code></td><td><code>"Run"</code></td><td>Button label</td></tr>
905
+ <tr><td><code>cta-icon</code></td><td>-</td><td>Domma icon name</td></tr>
906
+ <tr><td><code>cta-style</code></td><td><code>"primary"</code></td><td>Button variant</td></tr>
907
+ <tr><td><code>cta-confirm</code></td><td>-</td><td>Confirmation prompt</td></tr>
908
+ </tbody>
909
+ </table>
910
+ <p>All three display modes support CTA buttons: <strong>cards</strong> (card footer), <strong>list</strong> (inline), <strong>table</strong> (dedicated column).</p>
911
+ </div>
912
+ </div>
913
+
914
+ <div class="card card-collapsible mb-4">
915
+ <div class="card-header" role="button" tabindex="0">
916
+ <div class="card-header-content"><h2><span data-icon="book-open"></span> Full Reference</h2></div>
917
+ <span class="card-collapse-icon" data-icon="chevron-down"></span>
918
+ </div>
919
+ <div class="card-body docs-body">
920
+ <p>See the public documentation for live examples and the complete attribute reference:</p>
921
+ <a href="/resources/pro/cta" target="_blank" class="btn btn-ghost btn-sm">
922
+ <span data-icon="external-link"></span> CTA Shortcode Reference
923
+ </a>
924
+ </div>
925
+ </div>
926
+
927
+ </div><!-- /CTA tab -->
928
+
929
+ </div><!-- .tab-content -->
930
+ </div><!-- .tabs -->
931
+ ```
932
+
933
+ **Step 3: Commit**
934
+
935
+ ```bash
936
+ git add admin/js/views/pro-docs.js admin/js/templates/pro-docs.html
937
+ git commit -m "feat: add Pro Documentation admin view and template"
938
+ ```
939
+
940
+ ---
941
+
942
+ ## Task 7: Wire the view into the admin SPA
943
+
944
+ **Files:**
945
+ - Modify: `admin/js/views/index.js`
946
+ - Modify: `admin/js/app.js`
947
+ - Modify: `admin/js/config/sidebar-config.js`
948
+
949
+ **Step 1: Register the view in index.js**
950
+
951
+ Add to `admin/js/views/index.js`:
952
+
953
+ ```js
954
+ import {proDocsView} from './pro-docs.js';
955
+ ```
956
+
957
+ Add to the `views` export object:
958
+ ```js
959
+ proDocs: proDocsView,
960
+ ```
961
+
962
+ **Step 2: Add the route in app.js**
963
+
964
+ In the `coreRoutes` array in `admin/js/app.js`, add after the `actionEditor` route:
965
+
966
+ ```js
967
+ {path: '/pro/docs', view: 'proDocs', title: 'Pro Documentation - Domma CMS'},
968
+ ```
969
+
970
+ **Step 3: Add the sidebar entry in sidebar-config.js**
971
+
972
+ In `admin/js/config/sidebar-config.js`, add a new "Pro" section after the Documentation section (after the `api-reference` item, before `return items`):
973
+
974
+ ```js
975
+ if (canStructure) {
976
+ items.push(
977
+ {divider: true},
978
+ {heading: 'Pro'},
979
+ {
980
+ id: 'pro-docs',
981
+ text: 'Documentation',
982
+ icon: 'zap',
983
+ url: '#/pro/docs',
984
+ section: '#/pro/docs'
985
+ }
986
+ );
987
+ }
988
+ ```
989
+
990
+ **Step 4: Verify the route resolves**
991
+
992
+ Navigate to `http://localhost:4096/admin/#/pro/docs` in a browser (or check the server doesn't 404 on it - it's
993
+ client-side routing so the server always returns the admin shell).
994
+
995
+ ```bash
996
+ curl -s -o /dev/null -w "%{http_code}" http://localhost:4096/admin/
997
+ ```
998
+ Expected: `200`
999
+
1000
+ **Step 5: Commit**
1001
+
1002
+ ```bash
1003
+ git add admin/js/views/index.js admin/js/app.js admin/js/config/sidebar-config.js
1004
+ git commit -m "feat: wire Pro Documentation into admin SPA routes and sidebar"
1005
+ ```
1006
+
1007
+ ---
1008
+
1009
+ ## Verification Checklist
1010
+
1011
+ 1. `curl http://localhost:4096/resources/pro` → 200, renders hero + 3 cards
1012
+ 2. `curl http://localhost:4096/resources/pro/views` → 200, contains aggregation pipeline docs
1013
+ 3. `curl http://localhost:4096/resources/pro/actions` → 200, contains step types table
1014
+ 4. `curl http://localhost:4096/resources/pro/cta` → 200, contains `[cta]` syntax
1015
+ 5. `curl http://localhost:4096/resources` → contains "Pro Features" card text
1016
+ 6. Admin at `#/pro/docs` → three tabs render (Views, Actions, CTA Shortcode), icons and syntax highlighting active
1017
+ 7. Admin sidebar → "Pro" heading with "Documentation" link visible for admin/manager roles