domma-cms 0.6.5 → 0.6.7

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.
package/CLAUDE.md ADDED
@@ -0,0 +1,159 @@
1
+ # Domma CMS — AI Assistant Guide
2
+
3
+ ## Project Overview
4
+
5
+ This is a **Domma CMS** project. Stack: Fastify 5 (ESM) backend, Domma SPA admin, SSR public site.
6
+ Content is Markdown + YAML frontmatter in `content/pages/`. Config is JSON in `config/`.
7
+ Server runs on port **4096** by default (`config/server.json`).
8
+
9
+ ## Domma Framework — Use These, Not Vanilla JS
10
+
11
+ Domma provides built-in solutions. Never use vanilla JS equivalents.
12
+
13
+ | Alias | Purpose | NOT this |
14
+ |--------------------------------------------------|------------------------------------------|------------------------------------|
15
+ | `$('#el')` | DOM selection + manipulation | `document.querySelector()` |
16
+ | `S.set/get` | Storage | `localStorage.setItem/getItem` |
17
+ | `H.get/post/put/delete` | HTTP | `fetch()`, `XMLHttpRequest` |
18
+ | `D()` | Date manipulation (Moment-style) | Manual `Date` arithmetic |
19
+ | `_` | Array/object utils (`_.map`, `_.filter`) | Always evaluate if native suffices |
20
+ | `M.create(blueprint)` | Reactive data models | Manual state management |
21
+ | `F.create(selector, {blueprint})` | Form generation | Manual `<form>` HTML |
22
+ | `E.toast/confirm/modal/tabs/accordion/slideover` | UI components | Manual HTML/CSS/JS components |
23
+ | `I.scan()` / `<span data-icon="name">` | Icons | Manual SVG or icon fonts |
24
+ | `T.create(selector, {data, columns})` | Tables | Manual `<table>` generation |
25
+
26
+ ## Architecture
27
+
28
+ ```
29
+ server/ Fastify 5 API + SSR (DO NOT modify — upstream-replaced on update)
30
+ admin/ Domma SPA admin panel (DO NOT modify — upstream-replaced on update)
31
+ public/js/ Public site JS (site.js + component init)
32
+ public/css/ Site stylesheet (site.css is yours to edit)
33
+ content/pages/ Markdown pages (URL → file mapping below)
34
+ content/media/ Uploaded media
35
+ content/users/ User accounts (JSON)
36
+ content/collections/ Collection entries
37
+ config/ All configuration JSON (see Config section)
38
+ plugins/ CMS plugins (yours to create/modify)
39
+ docs/ Reference documentation
40
+ ```
41
+
42
+ **URL → file mapping:**
43
+
44
+ - `/` → `content/pages/index.md`
45
+ - `/about` → `content/pages/about.md`
46
+ - `/services` → `content/pages/services/index.md`
47
+
48
+ ## Content Pages
49
+
50
+ Pages are Markdown files with YAML frontmatter:
51
+
52
+ ```markdown
53
+ ---
54
+ title: Page Title
55
+ layout: default # default | landing | blank
56
+ description: SEO desc
57
+ ---
58
+
59
+ Page content here. Shortcodes work anywhere in the body.
60
+ ```
61
+
62
+ ### Shortcodes (18 types — full syntax in `docs/markdown-shortcodes.md`)
63
+
64
+ | Shortcode | Purpose |
65
+ |-----------------------------------------|----------------------------------------------------|
66
+ | `[card]` | Card container (optional title, collapsible, icon) |
67
+ | `[grid cols="N"]` / `[col]` | CSS Grid layout (Domma Grid — NOT `.col` class) |
68
+ | `[row]` / `[col]` | Row/column layout |
69
+ | `[slideover trigger="..." title="..."]` | Slide-over panel |
70
+ | `[dconfig]{...}[/dconfig]` | Declarative page config (JSON) |
71
+ | `[tabs]` / `[tab title="..."]` | Tab panels |
72
+ | `[accordion]` / `[item title="..."]` | Accordion sections |
73
+ | `[carousel]` / `[slide]` | Image/content carousel |
74
+ | `[hero title="..." tagline="..."]` | Hero section |
75
+ | `[table]` | Data table (Markdown table inside) |
76
+ | `[badge variant="..."]` | Badge/label |
77
+ | `[countdown to="..." /]` | Countdown timer |
78
+ | `[timeline]` / `[event]` | Timeline component |
79
+ | `[spacer /]` | Vertical spacer |
80
+ | `[center]` | Centre-align content |
81
+ | `[icon name="..." /]` | Inline icon |
82
+ | `[cta action="..."]` | Collection action trigger (admin) |
83
+
84
+ ### Shortcode Nesting Rules
85
+
86
+ Processing order (innermost first):
87
+
88
+ 1. `[dconfig]` — always first
89
+ 2. `[grid]` / `[row]` / `[col]`
90
+ 3. `[card]`
91
+ 4. `[tabs]`, `[accordion]`, `[carousel]`, `[hero]`, `[table]`, `[badge]`, `[countdown]`, `[timeline]`, `[spacer]`,
92
+ `[center]`, `[icon]`, `[cta]`
93
+ 5. `[slideover]` — always last (can contain anything above)
94
+
95
+ Safe nesting: `[card]` inside `[slideover]`, `[grid]` inside `[slideover]`, `[col]` inside `[grid]`.
96
+ Do NOT nest `[slideover]` inside another `[slideover]`.
97
+
98
+ ## Public Site Patterns
99
+
100
+ The server injects these globals on every public page:
101
+
102
+ ```js
103
+ window.__CMS_NAV__ // Navigation config (brand, items)
104
+ window.__CMS_SITE__ // Site config (title, theme, footer, smtp, etc.)
105
+ window.__CMS_DCONFIG__ // Page-level declarative config (merged with inline [dconfig])
106
+ ```
107
+
108
+ `public/js/site.js` reads these to initialise the Domma navbar, footer, and page components.
109
+ Domma components (tabs, accordion, carousel, etc.) in `.page-body` are auto-initialised by `site.js`.
110
+ Add custom public-site JS to `public/js/site.js` or new files loaded from `public/js/`.
111
+
112
+ ## Plugin Development
113
+
114
+ Each plugin needs exactly 3 files:
115
+
116
+ ```
117
+ plugins/my-plugin/
118
+ plugin.json Required manifest (name, displayName, version, description, author, date, icon)
119
+ plugin.js Default export: Fastify plugin function
120
+ config.js Default export: plain object of config defaults
121
+ ```
122
+
123
+ See `docs/plugin-development.md` for full plugin API, hooks, and injection points.
124
+
125
+ ## Config Reference
126
+
127
+ | File | Owner | Purpose |
128
+ |--------------------------|-----------------------|------------------------------------|
129
+ | `config/server.json` | CMS (merge on update) | Port, host, CORS, uploads |
130
+ | `config/auth.json` | CMS (merge on update) | JWT expiry, bcrypt rounds |
131
+ | `config/content.json` | CMS (merge on update) | Content dirs, page defaults |
132
+ | `config/presets.json` | CMS (merge on update) | Preset collection schemas |
133
+ | `config/site.json` | Yours | Site title, theme, footer, SMTP |
134
+ | `config/navigation.json` | Yours | Navbar brand + items |
135
+ | `config/plugins.json` | Yours | Plugin enabled/disabled + settings |
136
+
137
+ See `docs/configuration.md` for full schema reference.
138
+
139
+ ## Key Gotchas
140
+
141
+ 1. **Navigation sub-items**: use `items` key, NOT `children` — Domma navbar reads `items`.
142
+ 2. **Domma collections**: use `.get(0)` NOT `[0]` to get native DOM elements.
143
+ 3. **`.html()` strips interactive elements**: `E.modal().setContent(x)` also strips HTML — use light DOM slot
144
+ projection (`modal.element.appendChild(myDomElement)`) for buttons/inputs.
145
+ 4. **Landing layout**: `layout: landing` removes the standard page wrapper — add your own container CSS.
146
+ 5. **Grid shortcode**: uses Domma Grid (`grid`, `grid-cols-N`) — NOT the `.col` compatibility class.
147
+ 6. **Event delegation namespaces**: `$(doc).on('click.ns', '.sel', cb)` silently fails — use direct `addEventListener`
148
+ or unnamespaced `$(el).on('click', cb)`.
149
+ 7. **Tabs component classes**: wrapper `.tabs`, list `.tab-list`, trigger `button.tab-item`, panel `.tab-panel` (not
150
+ `.tabs-nav`, `.tabs-content`, `.tabs-pane`).
151
+
152
+ ## Docs
153
+
154
+ - `docs/getting-started.md` — Installation, first run, setup wizard
155
+ - `docs/markdown-shortcodes.md` — Full shortcode syntax and examples
156
+ - `docs/configuration.md` — Complete config schema for all JSON files
157
+ - `docs/plugin-development.md` — Plugin API, lifecycle hooks, injection points
158
+ - `docs/theming.md` — Available themes, CSS variables, customisation
159
+ - `docs/api-reference.md` — REST API endpoints (for headless / external integrations)
package/README.md CHANGED
@@ -77,7 +77,7 @@ my-site/
77
77
 
78
78
  ├── plugins/ # CMS plugins
79
79
  │ ├── domma-effects/
80
- │ ├── example-analytics/
80
+ │ ├── analytics/
81
81
  │ └── form-builder/
82
82
 
83
83
  ├── public/ # Public frontend assets (CSS, JS)
package/bin/cli.js CHANGED
@@ -237,7 +237,8 @@ const DEFAULT_NAV = {
237
237
  // Plugins enabled by default in a fresh project
238
238
  const ENABLED_BY_DEFAULT = new Set([
239
239
  'domma-effects',
240
- 'form-builder',
240
+ 'analytics',
241
+ 'theme-roller',
241
242
  ]);
242
243
 
243
244
  // Discover all plugins and set enabled state accordingly
@@ -1,19 +1,19 @@
1
- {
2
- "example-analytics": {
3
- "enabled": true,
4
- "settings": {}
5
- },
6
- "theme-roller": {
7
- "enabled": true,
8
- "settings": {}
9
- },
10
- "domma-effects": {
11
- "enabled": true,
12
- "settings": {
13
- "respectMotion": false,
14
- "defaultDuration": 600,
15
- "defaultAnimation": "fade",
16
- "defaultThreshold": 0.1
17
- }
18
- }
19
- }
1
+ {
2
+ "analytics": {
3
+ "enabled": true,
4
+ "settings": {}
5
+ },
6
+ "theme-roller": {
7
+ "enabled": true,
8
+ "settings": {}
9
+ },
10
+ "domma-effects": {
11
+ "enabled": true,
12
+ "settings": {
13
+ "respectMotion": false,
14
+ "defaultDuration": 600,
15
+ "defaultAnimation": "fade",
16
+ "defaultThreshold": 0.1
17
+ }
18
+ }
19
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "domma-cms",
3
- "version": "0.6.5",
3
+ "version": "0.6.7",
4
4
  "description": "File-based CMS powered by Domma and Fastify. Run npx domma-cms my-site to create a new project.",
5
5
  "type": "module",
6
6
  "main": "server/server.js",
@@ -29,7 +29,10 @@
29
29
  "build": "node scripts/build.js",
30
30
  "delete-users": "node -e \"import('fs').then(({readdirSync,rmSync})=>{const d='content/users';readdirSync(d).filter(f=>f.endsWith('.json')).forEach(f=>{rmSync(d+'/'+f);console.log('deleted',f)})})\"",
31
31
  "start": "node server/server.js",
32
- "start:cluster": "pm2 start server/server.js -i max --name domma-cms",
32
+ "pm2:start": "pm2 start ecosystem.config.cjs --env production",
33
+ "pm2:stop": "pm2 stop ecosystem.config.cjs",
34
+ "pm2:restart": "pm2 reload ecosystem.config.cjs",
35
+ "pm2:logs": "pm2 logs domma-cms",
33
36
  "dev": "node --watch server/server.js",
34
37
  "prod": "node server/server.js",
35
38
  "setup": "node scripts/setup.js",
@@ -1,14 +1,14 @@
1
1
  /**
2
- * Example Analytics Plugin — Server
2
+ * Analytics Plugin — Server
3
3
  * Tracks page hits in a JSON file alongside the plugin.
4
4
  * Endpoints:
5
- * POST /api/plugins/example-analytics/hit - public: record a hit { url }
6
- * GET /api/plugins/example-analytics/stats - admin: return all hit counts
7
- * DELETE /api/plugins/example-analytics/stats - admin: reset all stats
5
+ * POST /api/plugins/analytics/hit - public: record a hit { url }
6
+ * GET /api/plugins/analytics/stats - admin: return all hit counts
7
+ * DELETE /api/plugins/analytics/stats - admin: reset all stats
8
8
  */
9
9
  import fs from 'fs/promises';
10
10
  import path from 'path';
11
- import { fileURLToPath } from 'url';
11
+ import {fileURLToPath} from 'url';
12
12
 
13
13
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
14
14
  const STATS_FILE = path.join(__dirname, 'stats.json');
@@ -1,5 +1,5 @@
1
1
  {
2
- "name": "example-analytics",
2
+ "name": "analytics",
3
3
  "displayName": "Analytics",
4
4
  "version": "1.0.0",
5
5
  "description": "Basic page view analytics. Tracks hits per page using a simple JSON store.",
@@ -15,7 +15,7 @@
15
15
  ],
16
16
  "views": {
17
17
  "plugin-analytics": {
18
- "entry": "example-analytics/admin/views/analytics.js",
18
+ "entry": "analytics/admin/views/analytics.js",
19
19
  "exportName": "analyticsView"
20
20
  }
21
21
  }
@@ -1,9 +1,9 @@
1
- <!-- example-analytics: page view tracker -->
1
+ <!-- analytics: page view tracker -->
2
2
  <script>
3
3
  (function () {
4
4
  var url = window.location.pathname;
5
5
  if (typeof fetch === 'function') {
6
- fetch('/api/plugins/example-analytics/hit', {
6
+ fetch('/api/plugins/analytics/hit', {
7
7
  method: 'POST',
8
8
  headers: { 'Content-Type': 'application/json' },
9
9
  body: JSON.stringify({ url: url })
@@ -0,0 +1 @@
1
+ <!-- analytics: head injection (empty — tracking is done via body script) -->
@@ -1,12 +1,12 @@
1
1
  {
2
- "/": 138,
2
+ "/": 139,
3
3
  "/about": 71,
4
4
  "/blog": 30,
5
5
  "/contact": 30,
6
6
  "/resources/typography": 4,
7
7
  "/resources": 13,
8
8
  "/resources/shortcodes": 14,
9
- "/resources/cards": 15,
9
+ "/resources/cards": 16,
10
10
  "/resources/interactive": 13,
11
11
  "/resources/grid": 6,
12
12
  "/forms": 14,
package/scripts/build.js CHANGED
@@ -20,6 +20,7 @@ const COPY_AS_IS = [
20
20
  'scripts',
21
21
  'package.json',
22
22
  'README.md',
23
+ 'CLAUDE.md',
23
24
  'LICENSE',
24
25
  '.npmignore',
25
26
  ];
@@ -1 +0,0 @@
1
- <!-- example-analytics: head injection (empty — tracking is done via body script) -->
@@ -1,66 +0,0 @@
1
- {
2
- "slug": "contacts",
3
- "title": "Contacts",
4
- "description": "Contact Information",
5
- "fields": [
6
- {
7
- "name": "full_name",
8
- "type": "string",
9
- "label": "Full Name",
10
- "required": false,
11
- "placeholder": "Full Name",
12
- "helper": "Full Name",
13
- "minLength": 8,
14
- "maxLength": 255
15
- },
16
- {
17
- "type": "spacer"
18
- },
19
- {
20
- "name": "phone_number",
21
- "type": "tel",
22
- "label": "Phone Number",
23
- "required": false,
24
- "placeholder": "Phone Number",
25
- "helper": "Primary Phone Number"
26
- },
27
- {
28
- "type": "spacer"
29
- },
30
- {
31
- "name": "email_address",
32
- "type": "string",
33
- "label": "Email Address",
34
- "required": false,
35
- "placeholder": "Email Address",
36
- "helper": "Email Address",
37
- "minLength": 8,
38
- "maxLength": 255
39
- }
40
- ],
41
- "settings": {
42
- "submitText": "Submit",
43
- "successMessage": "Thank you for your submission.",
44
- "layout": "stacked",
45
- "honeypot": true,
46
- "rateLimitPerMinute": 3
47
- },
48
- "actions": {
49
- "email": {
50
- "enabled": false,
51
- "recipients": "",
52
- "subjectPrefix": "[Contacts]"
53
- },
54
- "webhook": {
55
- "enabled": false,
56
- "url": "",
57
- "method": "POST"
58
- },
59
- "collection": {
60
- "enabled": true,
61
- "slug": "contacts"
62
- }
63
- },
64
- "createdAt": "2026-03-17T12:35:44.569Z",
65
- "updatedAt": "2026-03-17T12:35:44.569Z"
66
- }
@@ -1,103 +0,0 @@
1
- {
2
- "slug": "enquiries",
3
- "title": "Enquiries",
4
- "description": "Get in touch with us",
5
- "fields": [
6
- {
7
- "name": "full_name",
8
- "type": "string",
9
- "label": "Full Name",
10
- "required": true,
11
- "placeholder": "Your full name",
12
- "helper": "",
13
- "validation": {
14
- "min": 2,
15
- "max": 100
16
- }
17
- },
18
- {
19
- "name": "email",
20
- "type": "email",
21
- "label": "Email Address",
22
- "required": true,
23
- "placeholder": "your@email.com",
24
- "helper": ""
25
- },
26
- {
27
- "name": "phone",
28
- "type": "tel",
29
- "label": "Phone Number",
30
- "required": false,
31
- "placeholder": "+44 7700 000000",
32
- "helper": "Optional"
33
- },
34
- {
35
- "name": "subject",
36
- "type": "select",
37
- "label": "Subject",
38
- "required": true,
39
- "placeholder": "Please select a subject",
40
- "helper": "",
41
- "options": [
42
- {
43
- "value": "general",
44
- "label": "General Enquiry"
45
- },
46
- {
47
- "value": "support",
48
- "label": "Support"
49
- },
50
- {
51
- "value": "sales",
52
- "label": "Sales"
53
- },
54
- {
55
- "value": "partnership",
56
- "label": "Partnership"
57
- },
58
- {
59
- "value": "other",
60
- "label": "Other"
61
- }
62
- ]
63
- },
64
- {
65
- "name": "message",
66
- "type": "textarea",
67
- "label": "Message",
68
- "required": true,
69
- "placeholder": "How can we help you?",
70
- "helper": "",
71
- "rows": 4,
72
- "validation": {
73
- "min": 10,
74
- "max": 2000
75
- }
76
- }
77
- ],
78
- "settings": {
79
- "submitText": "Send Message",
80
- "successMessage": "Thanks for reaching out! We'll get back to you shortly.",
81
- "layout": "stacked",
82
- "honeypot": true,
83
- "rateLimitPerMinute": 3
84
- },
85
- "actions": {
86
- "email": {
87
- "enabled": false,
88
- "recipients": "",
89
- "subjectPrefix": "[enquiries]"
90
- },
91
- "webhook": {
92
- "enabled": false,
93
- "url": "",
94
- "method": "POST"
95
- },
96
- "collection": {
97
- "enabled": true,
98
- "slug": "enquiries"
99
- }
100
- },
101
- "createdAt": "2026-03-17T12:35:44.569Z",
102
- "updatedAt": "2026-03-17T12:35:44.569Z"
103
- }
@@ -1,131 +0,0 @@
1
- {
2
- "slug": "feedback",
3
- "title": "Feedback",
4
- "description": "Share your feedback with us",
5
- "fields": [
6
- {
7
- "name": "name",
8
- "type": "string",
9
- "label": "Your Name",
10
- "required": true,
11
- "placeholder": "Please enter your full name",
12
- "helper": "Please enter your full name",
13
- "validation": {
14
- "min": 2,
15
- "max": 100
16
- }
17
- },
18
- {
19
- "name": "email",
20
- "type": "email",
21
- "label": "Email Address",
22
- "required": true,
23
- "placeholder": "your@email.com",
24
- "helper": "Please enter your email address"
25
- },
26
- {
27
- "name": "rating",
28
- "type": "select",
29
- "label": "Overall Rating",
30
- "required": true,
31
- "helper": "Tell us how we are doing!",
32
- "options": [
33
- {
34
- "value": "none",
35
- "label": "Please Choose"
36
- },
37
- {
38
- "value": "excellent",
39
- "label": "Excellent"
40
- },
41
- {
42
- "value": "good",
43
- "label": "Good"
44
- },
45
- {
46
- "value": "average",
47
- "label": "Average"
48
- },
49
- {
50
- "value": "poor",
51
- "label": "Poor"
52
- }
53
- ]
54
- },
55
- {
56
- "name": "category",
57
- "type": "select",
58
- "label": "Category",
59
- "required": true,
60
- "placeholder": "Please select a category",
61
- "helper": "",
62
- "options": [
63
- {
64
- "value": "general",
65
- "label": "General"
66
- },
67
- {
68
- "value": "bug-report",
69
- "label": "Bug Report"
70
- },
71
- {
72
- "value": "feature-request",
73
- "label": "Feature Request"
74
- },
75
- {
76
- "value": "praise",
77
- "label": "Praise"
78
- }
79
- ]
80
- },
81
- {
82
- "name": "subject",
83
- "type": "string",
84
- "label": "Subject",
85
- "required": true,
86
- "placeholder": "Brief summary of your feedback",
87
- "helper": "",
88
- "validation": {
89
- "max": 200
90
- }
91
- },
92
- {
93
- "name": "message",
94
- "type": "textarea",
95
- "label": "Your Feedback",
96
- "required": true,
97
- "placeholder": "Please share your thoughts in detail…",
98
- "helper": "Please share your thoughts in detail…",
99
- "rows": 4,
100
- "validation": {
101
- "min": 10,
102
- "max": 2000
103
- }
104
- }
105
- ],
106
- "settings": {
107
- "submitText": "Submit Feedback",
108
- "successMessage": "Thank you for your feedback! We appreciate you taking the time.",
109
- "layout": "stacked",
110
- "honeypot": true,
111
- "rateLimitPerMinute": 3
112
- },
113
- "actions": {
114
- "email": {
115
- "enabled": true,
116
- "recipients": "",
117
- "subjectPrefix": "[feedback]"
118
- },
119
- "webhook": {
120
- "enabled": false,
121
- "url": "",
122
- "method": "POST"
123
- },
124
- "collection": {
125
- "enabled": true,
126
- "slug": "feedback"
127
- }
128
- },
129
- "createdAt": "2026-03-17T12:35:44.569Z",
130
- "updatedAt": "2026-03-17T12:35:44.569Z"
131
- }
@@ -1,79 +0,0 @@
1
- {
2
- "slug": "notes",
3
- "title": "Notes",
4
- "description": "Free-form notes with categories and tags.",
5
- "fields": [
6
- {
7
- "name": "title",
8
- "type": "string",
9
- "label": "Title",
10
- "required": true,
11
- "placeholder": "Note title"
12
- },
13
- {
14
- "name": "content",
15
- "type": "textarea",
16
- "label": "Content",
17
- "required": true,
18
- "placeholder": "Write your note here…",
19
- "rows": 5
20
- },
21
- {
22
- "name": "category",
23
- "type": "select",
24
- "label": "Category",
25
- "required": false,
26
- "options": [
27
- {
28
- "value": "general",
29
- "label": "General"
30
- },
31
- {
32
- "value": "idea",
33
- "label": "Idea"
34
- },
35
- {
36
- "value": "reminder",
37
- "label": "Reminder"
38
- },
39
- {
40
- "value": "reference",
41
- "label": "Reference"
42
- }
43
- ]
44
- },
45
- {
46
- "name": "tags",
47
- "type": "string",
48
- "label": "Tags",
49
- "required": false,
50
- "placeholder": "Comma-separated tags",
51
- "helper": "Separate tags with commas"
52
- }
53
- ],
54
- "settings": {
55
- "submitText": "Save Note",
56
- "successMessage": "Note saved successfully.",
57
- "layout": "stacked",
58
- "honeypot": true,
59
- "rateLimitPerMinute": 3
60
- },
61
- "actions": {
62
- "email": {
63
- "enabled": false,
64
- "recipients": "",
65
- "subjectPrefix": "[notes]"
66
- },
67
- "webhook": {
68
- "enabled": false,
69
- "url": "",
70
- "method": "POST"
71
- },
72
- "collection": {
73
- "enabled": true,
74
- "slug": "notes"
75
- }
76
- },
77
- "createdAt": "2026-03-17T12:35:44.569Z",
78
- "updatedAt": "2026-03-17T12:35:44.569Z"
79
- }
@@ -1,100 +0,0 @@
1
- {
2
- "slug": "to-do",
3
- "title": "To-Do",
4
- "description": "Task tracking with status, priority, and due dates.",
5
- "fields": [
6
- {
7
- "name": "title",
8
- "type": "string",
9
- "label": "Title",
10
- "required": true,
11
- "placeholder": "Task title"
12
- },
13
- {
14
- "name": "description",
15
- "type": "textarea",
16
- "label": "Description",
17
- "required": false,
18
- "placeholder": "Task details…",
19
- "rows": 3
20
- },
21
- {
22
- "name": "status",
23
- "type": "select",
24
- "label": "Status",
25
- "required": true,
26
- "options": [
27
- {
28
- "value": "pending",
29
- "label": "Pending"
30
- },
31
- {
32
- "value": "in-progress",
33
- "label": "In Progress"
34
- },
35
- {
36
- "value": "done",
37
- "label": "Done"
38
- }
39
- ]
40
- },
41
- {
42
- "name": "priority",
43
- "type": "select",
44
- "label": "Priority",
45
- "required": false,
46
- "options": [
47
- {
48
- "value": "low",
49
- "label": "Low"
50
- },
51
- {
52
- "value": "medium",
53
- "label": "Medium"
54
- },
55
- {
56
- "value": "high",
57
- "label": "High"
58
- }
59
- ]
60
- },
61
- {
62
- "name": "due_date",
63
- "type": "date",
64
- "label": "Due Date",
65
- "required": false
66
- },
67
- {
68
- "name": "assigned_to",
69
- "type": "string",
70
- "label": "Assigned To",
71
- "required": false,
72
- "placeholder": "Name or email"
73
- }
74
- ],
75
- "settings": {
76
- "submitText": "Add Task",
77
- "successMessage": "Task added successfully.",
78
- "layout": "stacked",
79
- "honeypot": true,
80
- "rateLimitPerMinute": 3
81
- },
82
- "actions": {
83
- "email": {
84
- "enabled": false,
85
- "recipients": "",
86
- "subjectPrefix": "[to-do]"
87
- },
88
- "webhook": {
89
- "enabled": false,
90
- "url": "",
91
- "method": "POST"
92
- },
93
- "collection": {
94
- "enabled": true,
95
- "slug": "to-do"
96
- }
97
- },
98
- "createdAt": "2026-03-17T12:35:44.569Z",
99
- "updatedAt": "2026-03-17T12:35:44.569Z"
100
- }