domma-cms 0.9.10 → 0.12.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.
- package/CLAUDE.md +248 -159
- package/admin/css/admin.css +1 -1
- package/admin/js/api.js +1 -1
- package/admin/js/app.js +7 -3
- package/admin/js/config/sidebar-config.js +1 -1
- package/admin/js/http-interceptor.js +1 -0
- package/admin/js/lib/card-builder.js +2 -2
- package/admin/js/lib/markdown-toolbar.js +5 -5
- package/admin/js/lib/safe-html.js +1 -0
- package/admin/js/lib/shortcode-modal.js +1 -0
- package/admin/js/templates/layouts.html +5 -4
- package/admin/js/templates/notifications.html +14 -0
- package/admin/js/templates/plugin-marketplace.html +16 -0
- package/admin/js/templates/plugins.html +17 -5
- package/admin/js/views/index.js +1 -1
- package/admin/js/views/layouts.js +1 -16
- package/admin/js/views/notifications.js +1 -0
- package/admin/js/views/page-editor.js +37 -33
- package/admin/js/views/plugin-marketplace.js +1 -0
- package/admin/js/views/plugins.js +16 -16
- package/config/navigation.json +5 -72
- package/config/plugins.json +10 -14
- package/config/presets.json +50 -13
- package/config/site.json +11 -63
- package/package.json +2 -1
- package/plugins/_template/admin/templates/index.html +17 -0
- package/plugins/_template/admin/views/index.js +19 -0
- package/plugins/_template/config.js +8 -0
- package/plugins/_template/plugin.js +23 -0
- package/plugins/_template/plugin.json +34 -0
- package/plugins/analytics/plugin.json +41 -31
- package/plugins/blog/admin/templates/blog.html +22 -0
- package/plugins/blog/admin/templates/categories.html +7 -0
- package/plugins/blog/admin/templates/comments.html +11 -0
- package/plugins/blog/admin/templates/post-editor.html +97 -0
- package/plugins/blog/admin/templates/settings.html +11 -0
- package/plugins/blog/admin/views/blog.js +183 -0
- package/plugins/blog/admin/views/categories.js +235 -0
- package/plugins/blog/admin/views/comments.js +187 -0
- package/plugins/blog/admin/views/post-editor.js +291 -0
- package/plugins/blog/admin/views/settings.js +100 -0
- package/plugins/blog/collections/categories/schema.json +12 -0
- package/plugins/blog/collections/comments/schema.json +16 -0
- package/plugins/blog/collections/posts/schema.json +19 -0
- package/plugins/blog/config.js +8 -0
- package/plugins/blog/plugin.js +352 -0
- package/plugins/blog/plugin.json +96 -0
- package/plugins/blog/roles/blog-author.json +10 -0
- package/plugins/blog/roles/blog-editor.json +12 -0
- package/plugins/blog/templates/author.html +9 -0
- package/plugins/blog/templates/category.html +9 -0
- package/plugins/blog/templates/index.html +9 -0
- package/plugins/blog/templates/post.html +17 -0
- package/plugins/blog/templates/tag.html +9 -0
- package/plugins/contacts/collections/user-contact-groups/schema.json +1 -1
- package/plugins/contacts/collections/user-contacts/schema.json +1 -1
- package/plugins/contacts/plugin.js +4 -10
- package/plugins/contacts/plugin.json +13 -3
- package/plugins/notes/collections/user-notes/schema.json +1 -1
- package/plugins/notes/plugin.js +3 -9
- package/plugins/notes/plugin.json +13 -3
- package/plugins/site-search/plugin.json +5 -2
- package/plugins/theme-switcher/plugin.json +1 -1
- package/plugins/todo/collections/todos/schema.json +1 -1
- package/plugins/todo/plugin.js +3 -9
- package/plugins/todo/plugin.json +13 -3
- package/public/css/site.css +1 -1
- package/public/js/site.js +1 -1
- package/scripts/build.js +48 -0
- package/scripts/create-plugin.js +113 -0
- package/scripts/fresh.js +6 -7
- package/scripts/gen-instance-secret.js +46 -0
- package/scripts/reset.js +3 -3
- package/scripts/setup.js +31 -13
- package/server/middleware/auth.js +48 -0
- package/server/middleware/managerAuth.js +36 -0
- package/server/routes/api/actions.js +1 -1
- package/server/routes/api/auth.js +4 -3
- package/server/routes/api/layouts.js +173 -49
- package/server/routes/api/notifications.js +155 -0
- package/server/routes/api/plugin-marketplace.js +75 -0
- package/server/routes/api/users.js +1 -1
- package/server/routes/api/views.js +1 -1
- package/server/routes/public.js +4 -9
- package/server/server.js +32 -3
- package/server/services/actions.js +1 -1
- package/server/services/managerClient.js +182 -0
- package/server/services/markdown.js +76 -9
- package/server/services/permissionRegistry.js +245 -173
- package/server/services/pluginInstaller.js +301 -0
- package/server/services/plugins.js +117 -10
- package/server/services/presetCollections.js +66 -251
- package/server/services/renderer.js +99 -0
- package/server/services/roles.js +191 -39
- package/server/services/users.js +1 -1
- package/server/services/views.js +1 -1
- package/server/templates/page.html +2 -2
- package/plugins/docs/admin/templates/docs.html +0 -69
- package/plugins/docs/admin/views/docs.js +0 -276
- package/plugins/docs/config.js +0 -8
- package/plugins/docs/data/documents/57e003f0-68f2-47dc-9c36-ed4b10ed3deb.json +0 -11
- package/plugins/docs/data/folders.json +0 -9
- package/plugins/docs/data/templates.json +0 -1
- package/plugins/docs/data/versions/57e003f0-68f2-47dc-9c36-ed4b10ed3deb/1.json +0 -5
- package/plugins/docs/plugin.js +0 -375
- package/plugins/docs/plugin.json +0 -23
- package/plugins/form-builder/data/forms/contacts.json +0 -66
- package/plugins/form-builder/data/forms/enquiries.json +0 -103
- package/plugins/form-builder/data/forms/feedback.json +0 -131
- package/plugins/form-builder/data/forms/notes.json +0 -79
- package/plugins/form-builder/data/forms/to-do.json +0 -100
- package/plugins/form-builder/data/submissions/contacts.json +0 -1
- package/plugins/form-builder/data/submissions/enquiries.json +0 -1
- package/plugins/form-builder/data/submissions/feedback.json +0 -1
- package/plugins/form-builder/data/submissions/notes.json +0 -1
- package/plugins/form-builder/data/submissions/to-do.json +0 -1
- package/plugins/garage/admin/templates/garage.html +0 -111
- package/plugins/garage/admin/views/garage.js +0 -622
- package/plugins/garage/collections/garage-vehicles/schema.json +0 -101
- package/plugins/garage/config.js +0 -18
- package/plugins/garage/data/vehicles.json +0 -70
- package/plugins/garage/plugin.js +0 -398
- package/plugins/garage/plugin.json +0 -33
- package/scripts/seed.js +0 -1996
- package/server/services/userTypes.js +0 -227
package/scripts/seed.js
DELETED
|
@@ -1,1996 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Domma CMS — Seed Demo Content
|
|
4
|
-
* Creates sample pages and updates navigation.
|
|
5
|
-
* Safe to run multiple times — overwrites seed paths only.
|
|
6
|
-
* Run: npm run seed
|
|
7
|
-
*/
|
|
8
|
-
import {mkdir, writeFile} from 'node:fs/promises';
|
|
9
|
-
import path from 'node:path';
|
|
10
|
-
import {fileURLToPath} from 'node:url';
|
|
11
|
-
|
|
12
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
13
|
-
const ROOT = path.resolve(__dirname, '..');
|
|
14
|
-
|
|
15
|
-
const PAGES_DIR = path.join(ROOT, 'content', 'pages');
|
|
16
|
-
const COLLECTIONS_DIR = path.join(ROOT, 'content', 'collections');
|
|
17
|
-
const FORMS_DIR = path.join(ROOT, 'plugins', 'form-builder', 'data', 'forms');
|
|
18
|
-
const SUBS_DIR = path.join(ROOT, 'plugins', 'form-builder', 'data', 'submissions');
|
|
19
|
-
const NAV_CFG = path.join(ROOT, 'config', 'navigation.json');
|
|
20
|
-
|
|
21
|
-
const now = new Date().toISOString();
|
|
22
|
-
|
|
23
|
-
// ---------------------------------------------------------------------------
|
|
24
|
-
// Seed navigation
|
|
25
|
-
// ---------------------------------------------------------------------------
|
|
26
|
-
|
|
27
|
-
const SEED_NAV = {
|
|
28
|
-
brand: { text: 'My Site', logo: null, url: '/' },
|
|
29
|
-
items: [
|
|
30
|
-
{ text: 'Home', url: '/', icon: 'home' },
|
|
31
|
-
{ text: 'About', url: '/about', icon: 'info' },
|
|
32
|
-
{ text: 'Blog', url: '/blog', icon: 'book-open' },
|
|
33
|
-
{text: 'Contact', url: '/contact', icon: 'mail'},
|
|
34
|
-
{text: 'Feedback', url: '/feedback', icon: 'message-square'},
|
|
35
|
-
{
|
|
36
|
-
text: 'Resources', url: '/resources', icon: 'book-open',
|
|
37
|
-
items: [
|
|
38
|
-
{text: 'Overview', url: '/resources', icon: 'grid'},
|
|
39
|
-
{text: 'Typography', url: '/resources/typography', icon: 'type'},
|
|
40
|
-
{text: 'Grid System', url: '/resources/grid', icon: 'layout'},
|
|
41
|
-
{text: 'Cards', url: '/resources/cards', icon: 'credit-card'},
|
|
42
|
-
{text: 'Shortcode Reference', url: '/resources/shortcodes', icon: 'code'},
|
|
43
|
-
{text: 'Effects', url: '/resources/effects', icon: 'zap'},
|
|
44
|
-
{text: 'Interactive', url: '/resources/interactive', icon: 'mouse-pointer'}
|
|
45
|
-
]
|
|
46
|
-
}
|
|
47
|
-
],
|
|
48
|
-
variant: 'dark',
|
|
49
|
-
position: 'sticky'
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
// ---------------------------------------------------------------------------
|
|
53
|
-
// Page definitions
|
|
54
|
-
// ---------------------------------------------------------------------------
|
|
55
|
-
|
|
56
|
-
const PAGES = [
|
|
57
|
-
{
|
|
58
|
-
file: 'index.md',
|
|
59
|
-
fm: {
|
|
60
|
-
title: 'Welcome', slug: 'index',
|
|
61
|
-
description: 'Your new website, powered by Domma CMS',
|
|
62
|
-
layout: 'landing', status: 'published',
|
|
63
|
-
sortOrder: 1, showInNav: false, sidebar: false,
|
|
64
|
-
seo: { title: 'Welcome', description: 'Your new website, powered by Domma CMS' },
|
|
65
|
-
createdAt: now, updatedAt: now
|
|
66
|
-
},
|
|
67
|
-
body: `[hero fullwidth="true" variant="dark" size="lg" align="left" twinkle twinkle-count="30" blobs]
|
|
68
|
-
|
|
69
|
-
<span class="hero-label">File-Based CMS</span>
|
|
70
|
-
|
|
71
|
-
# [scribe speed="60" cursor="true"]The CMS that gets out of your way.[/scribe]
|
|
72
|
-
|
|
73
|
-
No databases. No bloat. Just Markdown, shortcodes, and a clean admin panel — content management the way it should be.
|
|
74
|
-
|
|
75
|
-
<div class="hero-cta"><a href="/admin/">Sign in to Admin →</a> <a href="/resources/">Browse Resources →</a></div>
|
|
76
|
-
|
|
77
|
-
[/hero]
|
|
78
|
-
|
|
79
|
-
[reveal animation="fade" delay="200"]
|
|
80
|
-
|
|
81
|
-
[grid cols="4" gap="4"]
|
|
82
|
-
|
|
83
|
-
[col]
|
|
84
|
-
[card]
|
|
85
|
-
[counter to="25" suffix="+" /]
|
|
86
|
-
**Shortcodes**
|
|
87
|
-
Powerful content blocks built right in.
|
|
88
|
-
[/card]
|
|
89
|
-
[/col]
|
|
90
|
-
|
|
91
|
-
[col]
|
|
92
|
-
[card]
|
|
93
|
-
[counter to="22" suffix="" /]
|
|
94
|
-
**Themes**
|
|
95
|
-
Light and dark colour schemes, zero configuration.
|
|
96
|
-
[/card]
|
|
97
|
-
[/col]
|
|
98
|
-
|
|
99
|
-
[col]
|
|
100
|
-
[card]
|
|
101
|
-
[counter to="3" suffix="" /]
|
|
102
|
-
**Plugins**
|
|
103
|
-
Extend with effects, analytics, and form handling.
|
|
104
|
-
[/card]
|
|
105
|
-
[/col]
|
|
106
|
-
|
|
107
|
-
[col]
|
|
108
|
-
[card]
|
|
109
|
-
[counter to="100" suffix="%" /]
|
|
110
|
-
**File-based**
|
|
111
|
-
Your content lives as plain files — always portable.
|
|
112
|
-
[/card]
|
|
113
|
-
[/col]
|
|
114
|
-
|
|
115
|
-
[/grid]
|
|
116
|
-
|
|
117
|
-
[/reveal]
|
|
118
|
-
|
|
119
|
-
## Features
|
|
120
|
-
|
|
121
|
-
[reveal animation="slide-up" delay="200"]
|
|
122
|
-
[grid cols="3" gap="4"]
|
|
123
|
-
|
|
124
|
-
[col]
|
|
125
|
-
[card title="Markdown Pages" icon="file-text" icon-layout="stacked" hover]
|
|
126
|
-
Write content in plain Markdown with YAML frontmatter. Add shortcodes anywhere for rich layouts — no HTML required.
|
|
127
|
-
[/card]
|
|
128
|
-
[/col]
|
|
129
|
-
|
|
130
|
-
[col]
|
|
131
|
-
[card title="Shortcode System" icon="code" icon-layout="stacked" hover]
|
|
132
|
-
From heroes to carousels, counters to accordions — drop expressive shortcodes directly into your Markdown.
|
|
133
|
-
[/card]
|
|
134
|
-
[/col]
|
|
135
|
-
|
|
136
|
-
[col]
|
|
137
|
-
[card title="Plugin Architecture" icon="code-block" icon-layout="stacked" hover]
|
|
138
|
-
Add effects, analytics, and forms through a clean plugin API. Each plugin ships its own routes, config, and admin UI.
|
|
139
|
-
[/card]
|
|
140
|
-
[/col]
|
|
141
|
-
|
|
142
|
-
[/grid]
|
|
143
|
-
[/reveal]
|
|
144
|
-
|
|
145
|
-
[spacer size="24" /]
|
|
146
|
-
|
|
147
|
-
[reveal animation="slide-up" delay="200"]
|
|
148
|
-
[hero variant="gradient-purple" size="md" fullwidth="true"]
|
|
149
|
-
|
|
150
|
-
## Ready to build?
|
|
151
|
-
|
|
152
|
-
[grid cols="2" gap="3"]
|
|
153
|
-
|
|
154
|
-
[col]
|
|
155
|
-
[ambient color="#a855f7"]
|
|
156
|
-
**[Sign in to the admin panel →](/admin/)**
|
|
157
|
-
Create pages, manage navigation, and configure your site.
|
|
158
|
-
[/ambient]
|
|
159
|
-
[/col]
|
|
160
|
-
|
|
161
|
-
[col]
|
|
162
|
-
[ambient color="#6366f1"]
|
|
163
|
-
**[Browse the resources →](/resources/)**
|
|
164
|
-
Guides, shortcode references, and plugin documentation.
|
|
165
|
-
[/ambient]
|
|
166
|
-
[/col]
|
|
167
|
-
|
|
168
|
-
[/grid]
|
|
169
|
-
|
|
170
|
-
[/hero]
|
|
171
|
-
[/reveal]
|
|
172
|
-
`
|
|
173
|
-
},
|
|
174
|
-
{
|
|
175
|
-
file: 'about.md',
|
|
176
|
-
fm: {
|
|
177
|
-
title: 'About', slug: 'about',
|
|
178
|
-
description: 'Learn more about us',
|
|
179
|
-
layout: 'default', status: 'published',
|
|
180
|
-
sortOrder: 2, showInNav: true, sidebar: false,
|
|
181
|
-
seo: { title: 'About', description: 'Learn more about us' },
|
|
182
|
-
createdAt: now, updatedAt: now
|
|
183
|
-
},
|
|
184
|
-
body: `[hero variant="dark" size="lg" fullwidth="true" twinkle twinkle-count="30" blobs]
|
|
185
|
-
|
|
186
|
-
# Build the web your way.
|
|
187
|
-
|
|
188
|
-
[scribe speed="35" cursor="true"]No databases. No lock-in. Just files, Markdown, and a CMS that stays out of your way.[/scribe]
|
|
189
|
-
|
|
190
|
-
[/hero]
|
|
191
|
-
|
|
192
|
-
[spacer /]
|
|
193
|
-
|
|
194
|
-
## What Domma CMS gives you
|
|
195
|
-
|
|
196
|
-
[reveal animation="slide-up"]
|
|
197
|
-
|
|
198
|
-
[grid cols="3" gap="4"]
|
|
199
|
-
[col]
|
|
200
|
-
[card title="25 Shortcodes"]
|
|
201
|
-
Layout blocks, scroll reveals, counters, heroes, accordions, typewriters — all available directly inside your Markdown. No HTML required.
|
|
202
|
-
[/card]
|
|
203
|
-
[/col]
|
|
204
|
-
[col]
|
|
205
|
-
[card title="22 Themes"]
|
|
206
|
-
Dark and light variants across 11 carefully crafted palettes. Switch instantly from the admin panel — no rebuild, no redeployment.
|
|
207
|
-
[/card]
|
|
208
|
-
[/col]
|
|
209
|
-
[col]
|
|
210
|
-
[card title="3 Plugins"]
|
|
211
|
-
Analytics, smart forms, and visual effects — ready to enable with a toggle. Extend your site without touching a line of code.
|
|
212
|
-
[/card]
|
|
213
|
-
[/col]
|
|
214
|
-
[/grid]
|
|
215
|
-
|
|
216
|
-
[/reveal]
|
|
217
|
-
|
|
218
|
-
[spacer /]
|
|
219
|
-
|
|
220
|
-
## By the numbers
|
|
221
|
-
|
|
222
|
-
[reveal animation="zoom"]
|
|
223
|
-
|
|
224
|
-
[grid cols="4" gap="4"]
|
|
225
|
-
[col]
|
|
226
|
-
<div style="text-align:center;padding:1.5rem 0">
|
|
227
|
-
|
|
228
|
-
## [counter to="25" suffix="+" /]
|
|
229
|
-
|
|
230
|
-
Shortcodes
|
|
231
|
-
|
|
232
|
-
</div>
|
|
233
|
-
[/col]
|
|
234
|
-
[col]
|
|
235
|
-
<div style="text-align:center;padding:1.5rem 0">
|
|
236
|
-
|
|
237
|
-
## [counter to="22" /]
|
|
238
|
-
|
|
239
|
-
Themes
|
|
240
|
-
|
|
241
|
-
</div>
|
|
242
|
-
[/col]
|
|
243
|
-
[col]
|
|
244
|
-
<div style="text-align:center;padding:1.5rem 0">
|
|
245
|
-
|
|
246
|
-
## [counter to="3" /]
|
|
247
|
-
|
|
248
|
-
Plugins
|
|
249
|
-
|
|
250
|
-
</div>
|
|
251
|
-
[/col]
|
|
252
|
-
[col]
|
|
253
|
-
<div style="text-align:center;padding:1.5rem 0">
|
|
254
|
-
|
|
255
|
-
## [counter to="100" suffix="%" /]
|
|
256
|
-
|
|
257
|
-
Markdown
|
|
258
|
-
|
|
259
|
-
</div>
|
|
260
|
-
[/col]
|
|
261
|
-
[/grid]
|
|
262
|
-
|
|
263
|
-
[/reveal]
|
|
264
|
-
|
|
265
|
-
[spacer /]
|
|
266
|
-
|
|
267
|
-
[breathe]
|
|
268
|
-
## Our philosophy
|
|
269
|
-
[/breathe]
|
|
270
|
-
|
|
271
|
-
[reveal animation="twinkle"]
|
|
272
|
-
|
|
273
|
-
Content belongs in files — not databases. Domma CMS is built on the conviction that a great publishing tool should be transparent, portable, and free from framework lock-in. Every page is a Markdown file. Every setting is plain JSON. Your content was yours before you installed Domma, and it will still be yours long after.
|
|
274
|
-
|
|
275
|
-
[/reveal]
|
|
276
|
-
|
|
277
|
-
[spacer size="32" /]
|
|
278
|
-
|
|
279
|
-
[breathe]
|
|
280
|
-
[card title="Explore the shortcode reference"]
|
|
281
|
-
Domma ships with 25 shortcodes covering layout, animation, interactivity, and more — all usable straight from the Markdown editor.
|
|
282
|
-
|
|
283
|
-
[Browse the full reference →](/resources/)
|
|
284
|
-
[/card]
|
|
285
|
-
[/breathe]
|
|
286
|
-
`
|
|
287
|
-
},
|
|
288
|
-
{
|
|
289
|
-
file: 'contact.md',
|
|
290
|
-
fm: {
|
|
291
|
-
title: 'Contact', slug: 'contact',
|
|
292
|
-
description: 'Get in touch',
|
|
293
|
-
layout: 'default', status: 'published',
|
|
294
|
-
sortOrder: 4, showInNav: true, sidebar: false,
|
|
295
|
-
seo: { title: 'Contact Us', description: 'Get in touch with us — we\'d love to hear from you' },
|
|
296
|
-
createdAt: now, updatedAt: now
|
|
297
|
-
},
|
|
298
|
-
body: `[hero variant="dark" size="lg" fullwidth="true" twinkle twinkle-count="50" blobs]
|
|
299
|
-
|
|
300
|
-
# Get in Touch
|
|
301
|
-
|
|
302
|
-
[scribe]We'd love to hear from you — drop us a message and we'll get back to you shortly.[/scribe]
|
|
303
|
-
|
|
304
|
-
[/hero]
|
|
305
|
-
|
|
306
|
-
[spacer /]
|
|
307
|
-
|
|
308
|
-
[grid cols="2" gap="4"]
|
|
309
|
-
|
|
310
|
-
[col]
|
|
311
|
-
|
|
312
|
-
[reveal animation="fade-up"]
|
|
313
|
-
[card title="Contact Information"]
|
|
314
|
-
|
|
315
|
-
<p><span data-icon="mail"></span> <strong>Email</strong><br>hello@example.com</p>
|
|
316
|
-
|
|
317
|
-
<p><span data-icon="phone"></span> <strong>Phone</strong><br>+44 20 0000 0000</p>
|
|
318
|
-
|
|
319
|
-
<p><span data-icon="clock"></span> <strong>Office Hours</strong><br>Monday – Friday, 9am – 5pm</p>
|
|
320
|
-
|
|
321
|
-
[/card]
|
|
322
|
-
[/reveal]
|
|
323
|
-
|
|
324
|
-
[spacer /]
|
|
325
|
-
|
|
326
|
-
[/col]
|
|
327
|
-
|
|
328
|
-
[col]
|
|
329
|
-
|
|
330
|
-
[reveal animation="fade-up"]
|
|
331
|
-
|
|
332
|
-
[card title="Send Us a Message"]
|
|
333
|
-
|
|
334
|
-
<div data-form="enquiries"></div>
|
|
335
|
-
|
|
336
|
-
[/card]
|
|
337
|
-
|
|
338
|
-
[/reveal]
|
|
339
|
-
|
|
340
|
-
[/col]
|
|
341
|
-
|
|
342
|
-
[/grid]
|
|
343
|
-
`
|
|
344
|
-
},
|
|
345
|
-
{
|
|
346
|
-
file: 'feedback.md',
|
|
347
|
-
fm: {
|
|
348
|
-
title: 'Feedback', slug: 'feedback',
|
|
349
|
-
description: 'Share your feedback with us',
|
|
350
|
-
layout: 'default', status: 'published',
|
|
351
|
-
sortOrder: 5, showInNav: true, sidebar: false,
|
|
352
|
-
seo: { title: 'Share Your Feedback', description: 'Help us improve by sharing your thoughts and experiences' },
|
|
353
|
-
createdAt: now, updatedAt: now
|
|
354
|
-
},
|
|
355
|
-
body: `[hero variant="dark" size="lg" fullwidth="true" twinkle twinkle-count="50" blobs]
|
|
356
|
-
|
|
357
|
-
# Share Your Feedback
|
|
358
|
-
|
|
359
|
-
[scribe]Your thoughts matter — help us improve by telling us about your experience.[/scribe]
|
|
360
|
-
|
|
361
|
-
[/hero]
|
|
362
|
-
|
|
363
|
-
[reveal animation="slide-up"]
|
|
364
|
-
|
|
365
|
-
[card title="Feedback Form"]
|
|
366
|
-
|
|
367
|
-
<div data-form="feedback"></div>
|
|
368
|
-
|
|
369
|
-
[/card]
|
|
370
|
-
|
|
371
|
-
[/reveal]
|
|
372
|
-
`
|
|
373
|
-
},
|
|
374
|
-
{
|
|
375
|
-
file: path.join('blog', 'index.md'),
|
|
376
|
-
fm: {
|
|
377
|
-
title: 'Blog', slug: 'blog',
|
|
378
|
-
description: 'News, updates and articles',
|
|
379
|
-
layout: 'landing', status: 'published',
|
|
380
|
-
sortOrder: 3, showInNav: true, sidebar: false,
|
|
381
|
-
seo: { title: 'Blog', description: 'News, updates and articles' },
|
|
382
|
-
createdAt: now, updatedAt: now
|
|
383
|
-
},
|
|
384
|
-
body: `[hero fullwidth="true" size="lg" variant="dark" align="left" twinkle twinkle-count="30" blobs]
|
|
385
|
-
|
|
386
|
-
## Blog & Articles
|
|
387
|
-
|
|
388
|
-
[scribe speed="45" cursor="true"]Ideas, guides, and updates.[/scribe]
|
|
389
|
-
|
|
390
|
-
[/hero]
|
|
391
|
-
|
|
392
|
-
[spacer size="40" /]
|
|
393
|
-
|
|
394
|
-
[reveal animation="slide-up" delay="0"]
|
|
395
|
-
[grid cols="3" gap="4"]
|
|
396
|
-
|
|
397
|
-
[col]
|
|
398
|
-
[card title="Getting Started"]
|
|
399
|
-
Your complete guide to creating pages, using shortcodes, and customising your site from scratch.
|
|
400
|
-
|
|
401
|
-
[Read more →](/blog/hello-world)
|
|
402
|
-
[/card]
|
|
403
|
-
[/col]
|
|
404
|
-
|
|
405
|
-
[col]
|
|
406
|
-
[card title="Write Your First Post"]
|
|
407
|
-
Everything you need to know about Markdown, frontmatter, and publishing content in Domma CMS.
|
|
408
|
-
|
|
409
|
-
[Read more →](/blog/hello-world)
|
|
410
|
-
[/card]
|
|
411
|
-
[/col]
|
|
412
|
-
|
|
413
|
-
[col]
|
|
414
|
-
[card title="Shortcode Primer"]
|
|
415
|
-
A quick tour of the most useful shortcodes — heroes, grids, cards, counters, and reveal animations.
|
|
416
|
-
|
|
417
|
-
[Read more →](/blog/hello-world)
|
|
418
|
-
[/card]
|
|
419
|
-
[/col]
|
|
420
|
-
|
|
421
|
-
[/grid]
|
|
422
|
-
[/reveal]
|
|
423
|
-
`
|
|
424
|
-
},
|
|
425
|
-
{
|
|
426
|
-
file: path.join('blog', 'hello-world.md'),
|
|
427
|
-
fm: {
|
|
428
|
-
title: 'Getting Started with Domma CMS', slug: 'hello-world',
|
|
429
|
-
description: 'A quick guide to creating pages, using shortcodes, and publishing content',
|
|
430
|
-
layout: 'default', status: 'published',
|
|
431
|
-
sortOrder: 1, showInNav: false, sidebar: false,
|
|
432
|
-
seo: { title: 'Getting Started', description: 'A quick guide to creating pages, using shortcodes, and publishing content' },
|
|
433
|
-
createdAt: now, updatedAt: now
|
|
434
|
-
},
|
|
435
|
-
body: `[hero variant="dark" size="lg" fullwidth="true" twinkle twinkle-count="30" blobs]
|
|
436
|
-
|
|
437
|
-
# Getting Started
|
|
438
|
-
|
|
439
|
-
[scribe speed="45" cursor="true"]Everything you need to start creating content with Domma CMS.[/scribe]
|
|
440
|
-
|
|
441
|
-
[/hero]
|
|
442
|
-
|
|
443
|
-
[spacer /]
|
|
444
|
-
|
|
445
|
-
[reveal animation="slide-up"]
|
|
446
|
-
[grid cols="3" gap="4"]
|
|
447
|
-
[col]
|
|
448
|
-
[card title="1. Create a page"]
|
|
449
|
-
Head to the admin panel, click **Pages → New Page**, give it a title and slug, then start writing in the Markdown editor.
|
|
450
|
-
[/card]
|
|
451
|
-
[/col]
|
|
452
|
-
[col]
|
|
453
|
-
[card title="2. Add shortcodes"]
|
|
454
|
-
Drop shortcodes anywhere in your content — \`[card]\`, \`[grid]\`, \`[hero]\`, \`[reveal]\` and more. The reference is at [/resources/shortcodes](/resources/shortcodes).
|
|
455
|
-
[/card]
|
|
456
|
-
[/col]
|
|
457
|
-
[col]
|
|
458
|
-
[card title="3. Publish"]
|
|
459
|
-
Set the page status to **Published** and save. It's live instantly — no build step, no deployment.
|
|
460
|
-
[/card]
|
|
461
|
-
[/col]
|
|
462
|
-
[/grid]
|
|
463
|
-
[/reveal]
|
|
464
|
-
|
|
465
|
-
[spacer /]
|
|
466
|
-
|
|
467
|
-
## Writing in Markdown
|
|
468
|
-
|
|
469
|
-
Domma CMS uses **Markdown** for all page content. The basics:
|
|
470
|
-
|
|
471
|
-
- **Bold** with \`**double asterisks**\`
|
|
472
|
-
- *Italic* with \`*single asterisks*\`
|
|
473
|
-
- \`Inline code\` with backticks
|
|
474
|
-
- [Links](https://example.com) with \`[text](url)\`
|
|
475
|
-
|
|
476
|
-
> Blockquotes with \`>\`
|
|
477
|
-
|
|
478
|
-
\`\`\`
|
|
479
|
-
Code blocks with triple backticks
|
|
480
|
-
\`\`\`
|
|
481
|
-
|
|
482
|
-
[spacer /]
|
|
483
|
-
|
|
484
|
-
[card title="Where to go next"]
|
|
485
|
-
- [Shortcode Reference →](/resources/shortcodes) — every shortcode with examples
|
|
486
|
-
- [Effects →](/resources/effects) — scroll reveals, counters, typewriter text
|
|
487
|
-
- [Admin panel →](/admin/) — manage pages, media, navigation, and settings
|
|
488
|
-
[/card]
|
|
489
|
-
`
|
|
490
|
-
},
|
|
491
|
-
|
|
492
|
-
// ----- Resources -----
|
|
493
|
-
|
|
494
|
-
{
|
|
495
|
-
file: path.join('resources', 'index.md'),
|
|
496
|
-
fm: {
|
|
497
|
-
title: 'Resources', slug: 'resources',
|
|
498
|
-
description: 'Reference pages showing the Domma CMS kit — typography, grid, cards, and shortcodes.',
|
|
499
|
-
layout: 'default', status: 'published',
|
|
500
|
-
sortOrder: 10, showInNav: false, sidebar: false,
|
|
501
|
-
seo: {title: 'Resources', description: 'Domma CMS component and shortcode reference'},
|
|
502
|
-
createdAt: now, updatedAt: now
|
|
503
|
-
},
|
|
504
|
-
body: `# Resources
|
|
505
|
-
|
|
506
|
-
Reference pages for content authors and developers working with Domma CMS.
|
|
507
|
-
|
|
508
|
-
[grid cols="2" gap="4"]
|
|
509
|
-
[col]
|
|
510
|
-
[card title="Typography"]
|
|
511
|
-
Headings, paragraphs, lists, blockquotes, inline code, and all standard Markdown elements.
|
|
512
|
-
|
|
513
|
-
[Read more →](/resources/typography)
|
|
514
|
-
[/card]
|
|
515
|
-
[/col]
|
|
516
|
-
[col]
|
|
517
|
-
[card title="Grid System"]
|
|
518
|
-
Equal columns, column spanning, gap sizes, and flexbox rows using the \`[grid]\`, \`[row]\`, and \`[col]\` shortcodes.
|
|
519
|
-
|
|
520
|
-
[Read more →](/resources/grid)
|
|
521
|
-
[/card]
|
|
522
|
-
[/col]
|
|
523
|
-
[col]
|
|
524
|
-
[card title="Cards"]
|
|
525
|
-
Card shortcode variants — basic, titled, collapsible, and cards inside grid layouts.
|
|
526
|
-
|
|
527
|
-
[Read more →](/resources/cards)
|
|
528
|
-
[/card]
|
|
529
|
-
[/col]
|
|
530
|
-
[col]
|
|
531
|
-
[card title="Shortcode Reference"]
|
|
532
|
-
Full reference for every shortcode supported in the editor, including all attributes and examples.
|
|
533
|
-
|
|
534
|
-
[Read more →](/resources/shortcodes)
|
|
535
|
-
[/card]
|
|
536
|
-
[/col]
|
|
537
|
-
[col]
|
|
538
|
-
[card title="Effects"]
|
|
539
|
-
Live demonstrations of every effect shortcode — scroll reveals, animated counters, typewriter text, ambient backgrounds,
|
|
540
|
-
and more.
|
|
541
|
-
|
|
542
|
-
[Read more →](/resources/effects)
|
|
543
|
-
[/card]
|
|
544
|
-
[/col]
|
|
545
|
-
[col]
|
|
546
|
-
[card title="Interactive"]
|
|
547
|
-
Live demos of \`[slideover]\` panels and \`[dconfig]\` declarative behaviour — toggle classes, show panels, and wire up
|
|
548
|
-
click handlers without writing JavaScript.
|
|
549
|
-
|
|
550
|
-
[Read more →](/resources/interactive)
|
|
551
|
-
[/card]
|
|
552
|
-
[/col]
|
|
553
|
-
[/grid]
|
|
554
|
-
`
|
|
555
|
-
},
|
|
556
|
-
{
|
|
557
|
-
file: path.join('resources', 'typography.md'),
|
|
558
|
-
fm: {
|
|
559
|
-
title: 'Typography', slug: 'typography',
|
|
560
|
-
description: 'Headings, paragraphs, lists, blockquotes, code, and all standard text elements.',
|
|
561
|
-
layout: 'default', status: 'published',
|
|
562
|
-
sortOrder: 11, showInNav: false, sidebar: false,
|
|
563
|
-
seo: {title: 'Typography — Resources', description: 'Typography reference for Domma CMS'},
|
|
564
|
-
createdAt: now, updatedAt: now
|
|
565
|
-
},
|
|
566
|
-
body: `# Typography
|
|
567
|
-
|
|
568
|
-
Everything you can express with standard Markdown in the Domma CMS editor.
|
|
569
|
-
|
|
570
|
-
---
|
|
571
|
-
|
|
572
|
-
## Headings
|
|
573
|
-
|
|
574
|
-
# Heading 1
|
|
575
|
-
## Heading 2
|
|
576
|
-
### Heading 3
|
|
577
|
-
#### Heading 4
|
|
578
|
-
##### Heading 5
|
|
579
|
-
###### Heading 6
|
|
580
|
-
|
|
581
|
-
---
|
|
582
|
-
|
|
583
|
-
## Paragraphs & Inline Styles
|
|
584
|
-
|
|
585
|
-
This is a regular paragraph. You can make text **bold**, _italic_, or ~~strikethrough~~. Combine them: **_bold and italic_**.
|
|
586
|
-
|
|
587
|
-
You can also write \`inline code\` using backticks.
|
|
588
|
-
|
|
589
|
-
---
|
|
590
|
-
|
|
591
|
-
## Blockquotes
|
|
592
|
-
|
|
593
|
-
> A blockquote stands out from body text and is useful for callouts, pull quotes, or attributed statements.
|
|
594
|
-
|
|
595
|
-
> Blockquotes can contain **inline formatting** and span multiple lines.
|
|
596
|
-
|
|
597
|
-
---
|
|
598
|
-
|
|
599
|
-
## Lists
|
|
600
|
-
|
|
601
|
-
### Unordered
|
|
602
|
-
|
|
603
|
-
- First item
|
|
604
|
-
- Second item
|
|
605
|
-
- Nested item
|
|
606
|
-
- Another nested item
|
|
607
|
-
- Third item
|
|
608
|
-
|
|
609
|
-
### Ordered
|
|
610
|
-
|
|
611
|
-
1. Step one
|
|
612
|
-
2. Step two
|
|
613
|
-
3. Step three
|
|
614
|
-
1. Sub-step
|
|
615
|
-
2. Sub-step
|
|
616
|
-
|
|
617
|
-
---
|
|
618
|
-
|
|
619
|
-
## Code
|
|
620
|
-
|
|
621
|
-
Inline code uses single backticks: \`npm run dev\`
|
|
622
|
-
|
|
623
|
-
Fenced code blocks use triple backticks:
|
|
624
|
-
|
|
625
|
-
\`\`\`js
|
|
626
|
-
function greet(name) {
|
|
627
|
-
return \\\`Hello, \\\${name}!\\\`;
|
|
628
|
-
}
|
|
629
|
-
\`\`\`
|
|
630
|
-
|
|
631
|
-
---
|
|
632
|
-
|
|
633
|
-
## Tables
|
|
634
|
-
|
|
635
|
-
| Column A | Column B | Column C |
|
|
636
|
-
|----------|----------|----------|
|
|
637
|
-
| Cell 1 | Cell 2 | Cell 3 |
|
|
638
|
-
| Cell 4 | Cell 5 | Cell 6 |
|
|
639
|
-
|
|
640
|
-
---
|
|
641
|
-
|
|
642
|
-
← [Back to Resources](/resources)
|
|
643
|
-
`
|
|
644
|
-
},
|
|
645
|
-
{
|
|
646
|
-
file: path.join('resources', 'grid.md'),
|
|
647
|
-
fm: {
|
|
648
|
-
title: 'Grid System', slug: 'grid',
|
|
649
|
-
description: 'Equal columns, column spanning, gap sizes, and flexbox rows using grid shortcodes.',
|
|
650
|
-
layout: 'default', status: 'published',
|
|
651
|
-
sortOrder: 12, showInNav: false, sidebar: false,
|
|
652
|
-
seo: {title: 'Grid System — Resources', description: 'Domma CMS grid shortcode reference'},
|
|
653
|
-
createdAt: now, updatedAt: now
|
|
654
|
-
},
|
|
655
|
-
body: `# Grid System
|
|
656
|
-
|
|
657
|
-
Domma uses native CSS Grid via shortcodes. Use \`[grid]\`, \`[row]\`, and \`[col]\` in the editor — no HTML needed.
|
|
658
|
-
|
|
659
|
-
---
|
|
660
|
-
|
|
661
|
-
## Equal Columns
|
|
662
|
-
|
|
663
|
-
### 2 Columns
|
|
664
|
-
|
|
665
|
-
[grid cols="2" gap="4"]
|
|
666
|
-
[col]
|
|
667
|
-
**Left column**
|
|
668
|
-
Each \`[col]\` fills one track of the grid automatically.
|
|
669
|
-
[/col]
|
|
670
|
-
[col]
|
|
671
|
-
**Right column**
|
|
672
|
-
No extra attributes needed for equal widths.
|
|
673
|
-
[/col]
|
|
674
|
-
[/grid]
|
|
675
|
-
|
|
676
|
-
### 3 Columns
|
|
677
|
-
|
|
678
|
-
[grid cols="3" gap="4"]
|
|
679
|
-
[col]**One** — first of three.[/col]
|
|
680
|
-
[col]**Two** — second of three.[/col]
|
|
681
|
-
[col]**Three** — third of three.[/col]
|
|
682
|
-
[/grid]
|
|
683
|
-
|
|
684
|
-
### 4 Columns
|
|
685
|
-
|
|
686
|
-
[grid cols="4" gap="3"]
|
|
687
|
-
[col]Alpha[/col]
|
|
688
|
-
[col]Beta[/col]
|
|
689
|
-
[col]Gamma[/col]
|
|
690
|
-
[col]Delta[/col]
|
|
691
|
-
[/grid]
|
|
692
|
-
|
|
693
|
-
---
|
|
694
|
-
|
|
695
|
-
## Column Spanning
|
|
696
|
-
|
|
697
|
-
Use \`span="N"\` on a \`[col]\` to make it span more than one track. Values must add up to \`cols\`.
|
|
698
|
-
|
|
699
|
-
### 8 / 4 split
|
|
700
|
-
|
|
701
|
-
[grid cols="12" gap="4"]
|
|
702
|
-
[col span="8"]**span="8"** — main content area (two-thirds).[/col]
|
|
703
|
-
[col span="4"]**span="4"** — sidebar (one-third).[/col]
|
|
704
|
-
[/grid]
|
|
705
|
-
|
|
706
|
-
### 6 / 6 (halves)
|
|
707
|
-
|
|
708
|
-
[grid cols="12" gap="4"]
|
|
709
|
-
[col span="6"]**span="6"** — left half.[/col]
|
|
710
|
-
[col span="6"]**span="6"** — right half.[/col]
|
|
711
|
-
[/grid]
|
|
712
|
-
|
|
713
|
-
### 9 / 3
|
|
714
|
-
|
|
715
|
-
[grid cols="12" gap="4"]
|
|
716
|
-
[col span="9"]**span="9"** — wide column.[/col]
|
|
717
|
-
[col span="3"]**span="3"** — narrow aside.[/col]
|
|
718
|
-
[/grid]
|
|
719
|
-
|
|
720
|
-
---
|
|
721
|
-
|
|
722
|
-
## Gap Sizes
|
|
723
|
-
|
|
724
|
-
**gap="1"**
|
|
725
|
-
[grid cols="4" gap="1"]
|
|
726
|
-
[col]One[/col][col]Two[/col][col]Three[/col][col]Four[/col]
|
|
727
|
-
[/grid]
|
|
728
|
-
|
|
729
|
-
**gap="3"**
|
|
730
|
-
[grid cols="4" gap="3"]
|
|
731
|
-
[col]One[/col][col]Two[/col][col]Three[/col][col]Four[/col]
|
|
732
|
-
[/grid]
|
|
733
|
-
|
|
734
|
-
**gap="6"**
|
|
735
|
-
[grid cols="4" gap="6"]
|
|
736
|
-
[col]One[/col][col]Two[/col][col]Three[/col][col]Four[/col]
|
|
737
|
-
[/grid]
|
|
738
|
-
|
|
739
|
-
---
|
|
740
|
-
|
|
741
|
-
## Row (Flexbox)
|
|
742
|
-
|
|
743
|
-
\`[row]\` uses flexbox — columns share available space equally without specifying a count.
|
|
744
|
-
|
|
745
|
-
[row gap="4"]
|
|
746
|
-
[col]**Flex col 1**[/col]
|
|
747
|
-
[col]**Flex col 2**[/col]
|
|
748
|
-
[col]**Flex col 3**[/col]
|
|
749
|
-
[/row]
|
|
750
|
-
|
|
751
|
-
---
|
|
752
|
-
|
|
753
|
-
← [Back to Resources](/resources)
|
|
754
|
-
`
|
|
755
|
-
},
|
|
756
|
-
{
|
|
757
|
-
file: path.join('resources', 'cards.md'),
|
|
758
|
-
fm: {
|
|
759
|
-
title: 'Cards', slug: 'cards',
|
|
760
|
-
description: 'Card shortcode variants — basic, titled, collapsible, and cards in grid layouts.',
|
|
761
|
-
layout: 'default', status: 'published',
|
|
762
|
-
sortOrder: 13, showInNav: false, sidebar: false,
|
|
763
|
-
seo: {title: 'Cards — Resources', description: 'Domma CMS card shortcode reference'},
|
|
764
|
-
createdAt: now, updatedAt: now
|
|
765
|
-
},
|
|
766
|
-
body: `# Cards
|
|
767
|
-
|
|
768
|
-
The \`[card]\` shortcode wraps content in a styled card. Cards support full Markdown inside them, including other shortcodes.
|
|
769
|
-
|
|
770
|
-
---
|
|
771
|
-
|
|
772
|
-
## Basic Card (no header)
|
|
773
|
-
|
|
774
|
-
[card]
|
|
775
|
-
This is a basic card with no title. Useful for callout blocks or highlighted sections.
|
|
776
|
-
|
|
777
|
-
It supports **bold**, _italic_, and \`inline code\`.
|
|
778
|
-
[/card]
|
|
779
|
-
|
|
780
|
-
---
|
|
781
|
-
|
|
782
|
-
## Card with Title
|
|
783
|
-
|
|
784
|
-
[card title="Card Title"]
|
|
785
|
-
This card has a header. The \`title\` attribute sets the text in the card's top bar.
|
|
786
|
-
[/card]
|
|
787
|
-
|
|
788
|
-
---
|
|
789
|
-
|
|
790
|
-
## Collapsible Card
|
|
791
|
-
|
|
792
|
-
Add \`collapsible="true"\` to make the body toggle on header click. Starts collapsed.
|
|
793
|
-
|
|
794
|
-
[card title="Click to expand" collapsible="true"]
|
|
795
|
-
This content is hidden by default and revealed when the header is clicked.
|
|
796
|
-
[/card]
|
|
797
|
-
|
|
798
|
-
---
|
|
799
|
-
|
|
800
|
-
## Cards in a Grid
|
|
801
|
-
|
|
802
|
-
[grid cols="3" gap="4"]
|
|
803
|
-
[col]
|
|
804
|
-
[card title="Feature One"]
|
|
805
|
-
Describe the first feature here. One or two sentences works well in a three-column layout.
|
|
806
|
-
[/card]
|
|
807
|
-
[/col]
|
|
808
|
-
[col]
|
|
809
|
-
[card title="Feature Two"]
|
|
810
|
-
Cards in a grid automatically share the same height within a row.
|
|
811
|
-
[/card]
|
|
812
|
-
[/col]
|
|
813
|
-
[col]
|
|
814
|
-
[card title="Feature Three"]
|
|
815
|
-
Add a link if this feature has its own dedicated page.
|
|
816
|
-
[/card]
|
|
817
|
-
[/col]
|
|
818
|
-
[/grid]
|
|
819
|
-
|
|
820
|
-
---
|
|
821
|
-
|
|
822
|
-
## Grid Inside a Card
|
|
823
|
-
|
|
824
|
-
[card title="Two-column layout inside a card"]
|
|
825
|
-
[grid cols="2" gap="4"]
|
|
826
|
-
[col]
|
|
827
|
-
Use the left column for a description or introductory copy.
|
|
828
|
-
[/col]
|
|
829
|
-
[col]
|
|
830
|
-
Use the right column for a list or supplementary detail.
|
|
831
|
-
|
|
832
|
-
- Point A
|
|
833
|
-
- Point B
|
|
834
|
-
- Point C
|
|
835
|
-
[/col]
|
|
836
|
-
[/grid]
|
|
837
|
-
[/card]
|
|
838
|
-
|
|
839
|
-
---
|
|
840
|
-
|
|
841
|
-
← [Back to Resources](/resources)
|
|
842
|
-
`
|
|
843
|
-
},
|
|
844
|
-
{
|
|
845
|
-
file: path.join('resources', 'shortcodes.md'),
|
|
846
|
-
fm: {
|
|
847
|
-
title: 'Shortcode Reference', slug: 'shortcodes',
|
|
848
|
-
description: 'Full reference for every shortcode supported in the Domma CMS editor.',
|
|
849
|
-
layout: 'default', status: 'published',
|
|
850
|
-
sortOrder: 14, showInNav: false, sidebar: false,
|
|
851
|
-
seo: {title: 'Shortcode Reference — Resources', description: 'Complete shortcode reference for Domma CMS'},
|
|
852
|
-
createdAt: now, updatedAt: now
|
|
853
|
-
},
|
|
854
|
-
body: `# Shortcode Reference
|
|
855
|
-
|
|
856
|
-
Shortcodes extend Markdown with layout and component capabilities. Mix them freely with regular Markdown.
|
|
857
|
-
|
|
858
|
-
**Syntax:** \`[shortcode attribute="value"]…[/shortcode]\`
|
|
859
|
-
|
|
860
|
-
---
|
|
861
|
-
|
|
862
|
-
## [\`grid\`]
|
|
863
|
-
|
|
864
|
-
Creates a CSS Grid container.
|
|
865
|
-
|
|
866
|
-
| Attribute | Required | Description |
|
|
867
|
-
|-----------|----------|-------------|
|
|
868
|
-
| \`cols\` | Yes | Number of columns (1–12) |
|
|
869
|
-
| \`gap\` | No | Gap between cells (1–6) |
|
|
870
|
-
| \`class\` | No | Extra CSS classes |
|
|
871
|
-
|
|
872
|
-
[grid cols="3" gap="4"]
|
|
873
|
-
[col]**cols="3"**[/col]
|
|
874
|
-
[col]**gap="4"**[/col]
|
|
875
|
-
[col]**Equal widths**[/col]
|
|
876
|
-
[/grid]
|
|
877
|
-
|
|
878
|
-
---
|
|
879
|
-
|
|
880
|
-
## [\`row\`]
|
|
881
|
-
|
|
882
|
-
Flexbox row — columns share available width equally, no \`cols\` needed.
|
|
883
|
-
|
|
884
|
-
| Attribute | Required | Description |
|
|
885
|
-
|-----------|----------|-------------|
|
|
886
|
-
| \`gap\` | No | Gap between columns (1–6) |
|
|
887
|
-
| \`class\` | No | Extra CSS classes |
|
|
888
|
-
|
|
889
|
-
[row gap="4"]
|
|
890
|
-
[col]**Left**[/col]
|
|
891
|
-
[col]**Right**[/col]
|
|
892
|
-
[/row]
|
|
893
|
-
|
|
894
|
-
---
|
|
895
|
-
|
|
896
|
-
## [\`col\`]
|
|
897
|
-
|
|
898
|
-
A column inside \`[grid]\` or \`[row]\`. Content is rendered as Markdown.
|
|
899
|
-
|
|
900
|
-
| Attribute | Required | Description |
|
|
901
|
-
|-----------|----------|-------------|
|
|
902
|
-
| \`span\` | No | Columns to span (values must sum to grid \`cols\`) |
|
|
903
|
-
| \`class\` | No | Extra CSS classes |
|
|
904
|
-
|
|
905
|
-
[grid cols="12" gap="4"]
|
|
906
|
-
[col span="8"]**span="8"** — main content[/col]
|
|
907
|
-
[col span="4"]**span="4"** — sidebar[/col]
|
|
908
|
-
[/grid]
|
|
909
|
-
|
|
910
|
-
---
|
|
911
|
-
|
|
912
|
-
## [\`card\`]
|
|
913
|
-
|
|
914
|
-
Wraps content in a styled card.
|
|
915
|
-
|
|
916
|
-
| Attribute | Required | Description |
|
|
917
|
-
|-----------|----------|-------------|
|
|
918
|
-
| \`title\` | No | Card header text |
|
|
919
|
-
| \`collapsible\` | No | \`"true"\` to toggle body on header click |
|
|
920
|
-
| \`class\` | No | Extra CSS classes |
|
|
921
|
-
|
|
922
|
-
[card title="Example card"]
|
|
923
|
-
Markdown **works** inside cards, including _italic_, \`code\`, and shortcodes.
|
|
924
|
-
[/card]
|
|
925
|
-
|
|
926
|
-
[card title="Collapsible" collapsible="true"]
|
|
927
|
-
This body starts collapsed.
|
|
928
|
-
[/card]
|
|
929
|
-
|
|
930
|
-
---
|
|
931
|
-
|
|
932
|
-
## Embedding a Form
|
|
933
|
-
|
|
934
|
-
Paste this HTML anywhere in your Markdown to embed a form:
|
|
935
|
-
|
|
936
|
-
\`\`\`html
|
|
937
|
-
<div data-form="your-form-slug"></div>
|
|
938
|
-
\`\`\`
|
|
939
|
-
|
|
940
|
-
Replace \`your-form-slug\` with the slug from the Form Builder. Example:
|
|
941
|
-
|
|
942
|
-
\`\`\`html
|
|
943
|
-
<div data-form="enquiries"></div>
|
|
944
|
-
\`\`\`
|
|
945
|
-
|
|
946
|
-
---
|
|
947
|
-
|
|
948
|
-
## [\`slideover\`]
|
|
949
|
-
|
|
950
|
-
Renders a trigger button that opens a slide-in panel with Markdown content.
|
|
951
|
-
|
|
952
|
-
| Attribute | Required | Description |
|
|
953
|
-
|-----------|----------|-------------|
|
|
954
|
-
| \`title\` | No | Panel header text |
|
|
955
|
-
| \`trigger\` | No | Button label (default: \`"Open"\`) |
|
|
956
|
-
| \`size\` | No | \`sm\`, \`md\` (default), \`lg\` |
|
|
957
|
-
| \`position\` | No | \`right\` (default) or \`left\` |
|
|
958
|
-
|
|
959
|
-
\`\`\`
|
|
960
|
-
[slideover title="More Info" trigger="Read more" size="md"]
|
|
961
|
-
Markdown here — cards, grids, and other shortcodes work inside.
|
|
962
|
-
[/slideover]
|
|
963
|
-
\`\`\`
|
|
964
|
-
|
|
965
|
-
---
|
|
966
|
-
|
|
967
|
-
## [\`dconfig\`]
|
|
968
|
-
|
|
969
|
-
Declarative behaviour — wires up click handlers and class toggles from JSON, no JavaScript needed.
|
|
970
|
-
|
|
971
|
-
\`\`\`
|
|
972
|
-
[dconfig]
|
|
973
|
-
{
|
|
974
|
-
"#my-btn": {
|
|
975
|
-
"events": {
|
|
976
|
-
"click": { "target": "#panel", "toggleClass": "hidden" }
|
|
977
|
-
}
|
|
978
|
-
}
|
|
979
|
-
}
|
|
980
|
-
[/dconfig]
|
|
981
|
-
\`\`\`
|
|
982
|
-
|
|
983
|
-
You can also set DConfig from the **DConfig section** in the page editor. Inline shortcodes win on selector conflict.
|
|
984
|
-
See [Interactive demos →](/resources/interactive)
|
|
985
|
-
|
|
986
|
-
---
|
|
987
|
-
|
|
988
|
-
← [Back to Resources](/resources)
|
|
989
|
-
`
|
|
990
|
-
},
|
|
991
|
-
|
|
992
|
-
// ----- Effects -----
|
|
993
|
-
{
|
|
994
|
-
file: path.join('resources', 'effects.md'),
|
|
995
|
-
fm: {
|
|
996
|
-
title: 'Effects', slug: 'effects',
|
|
997
|
-
description: 'Live demonstrations of every Domma Effects shortcode — reveals, counters, typewriter text, ambient backgrounds, and more.',
|
|
998
|
-
layout: 'default', status: 'published',
|
|
999
|
-
sortOrder: 15, showInNav: false, sidebar: false,
|
|
1000
|
-
seo: {title: 'Effects — Resources', description: 'Live demonstrations of Domma Effects shortcodes'},
|
|
1001
|
-
createdAt: now, updatedAt: now
|
|
1002
|
-
},
|
|
1003
|
-
body: `# Effects
|
|
1004
|
-
|
|
1005
|
-
Effect shortcodes bring content to life. All examples below are live (requires the Domma Effects plugin).
|
|
1006
|
-
|
|
1007
|
-
---
|
|
1008
|
-
|
|
1009
|
-
## \`[reveal]\` — Scroll-triggered entrance
|
|
1010
|
-
|
|
1011
|
-
[reveal animation="fade"]
|
|
1012
|
-
[card title="Fade in"]
|
|
1013
|
-
This card faded in as you scrolled to it.
|
|
1014
|
-
[/card]
|
|
1015
|
-
[/reveal]
|
|
1016
|
-
|
|
1017
|
-
\`\`\`
|
|
1018
|
-
[reveal animation="fade"]
|
|
1019
|
-
Your content here.
|
|
1020
|
-
[/reveal]
|
|
1021
|
-
\`\`\`
|
|
1022
|
-
|
|
1023
|
-
**Attributes:** \`animation\` (fade, slide-up, zoom, flip) · \`duration\` (ms) · \`delay\` (ms) · \`once\` (true/false)
|
|
1024
|
-
|
|
1025
|
-
---
|
|
1026
|
-
|
|
1027
|
-
## \`[counter]\` — Animated number
|
|
1028
|
-
|
|
1029
|
-
[reveal animation="slide-up"]
|
|
1030
|
-
[grid cols="3" gap="4"]
|
|
1031
|
-
[col]<div style="text-align:center;padding:1rem 0">
|
|
1032
|
-
|
|
1033
|
-
## [counter to="247" separator="," /]
|
|
1034
|
-
|
|
1035
|
-
Pages published
|
|
1036
|
-
</div>[/col]
|
|
1037
|
-
[col]<div style="text-align:center;padding:1rem 0">
|
|
1038
|
-
|
|
1039
|
-
## [counter to="98" suffix="%" /]
|
|
1040
|
-
|
|
1041
|
-
Uptime
|
|
1042
|
-
</div>[/col]
|
|
1043
|
-
[col]<div style="text-align:center;padding:1rem 0">
|
|
1044
|
-
|
|
1045
|
-
## [counter to="12" /]
|
|
1046
|
-
|
|
1047
|
-
Plugins
|
|
1048
|
-
</div>[/col]
|
|
1049
|
-
[/grid]
|
|
1050
|
-
[/reveal]
|
|
1051
|
-
|
|
1052
|
-
\`\`\`
|
|
1053
|
-
[counter to="100" prefix="$" suffix="+" /]
|
|
1054
|
-
\`\`\`
|
|
1055
|
-
|
|
1056
|
-
---
|
|
1057
|
-
|
|
1058
|
-
## \`[scribe]\` — Typewriter
|
|
1059
|
-
|
|
1060
|
-
[reveal animation="fade"]
|
|
1061
|
-
[card]
|
|
1062
|
-
[scribe speed="40" cursor="true"]
|
|
1063
|
-
Domma CMS — fast, flexible, file-based.
|
|
1064
|
-
[/scribe]
|
|
1065
|
-
[/card]
|
|
1066
|
-
[/reveal]
|
|
1067
|
-
|
|
1068
|
-
---
|
|
1069
|
-
|
|
1070
|
-
## \`[animate]\` — CSS-only animation
|
|
1071
|
-
|
|
1072
|
-
[grid cols="3" gap="4"]
|
|
1073
|
-
[col]
|
|
1074
|
-
[animate type="fade-in-up"]
|
|
1075
|
-
[card title="fade-in-up"]
|
|
1076
|
-
No plugin needed.
|
|
1077
|
-
[/card]
|
|
1078
|
-
[/animate]
|
|
1079
|
-
[/col]
|
|
1080
|
-
[col]
|
|
1081
|
-
[animate type="zoom-in"]
|
|
1082
|
-
[card title="zoom-in"]
|
|
1083
|
-
Scales up from centre.
|
|
1084
|
-
[/card]
|
|
1085
|
-
[/animate]
|
|
1086
|
-
[/col]
|
|
1087
|
-
[col]
|
|
1088
|
-
[animate type="fade-in-left"]
|
|
1089
|
-
[card title="fade-in-left"]
|
|
1090
|
-
Slides in from right.
|
|
1091
|
-
[/card]
|
|
1092
|
-
[/animate]
|
|
1093
|
-
[/col]
|
|
1094
|
-
[/grid]
|
|
1095
|
-
|
|
1096
|
-
---
|
|
1097
|
-
|
|
1098
|
-
← [Back to Resources](/resources)
|
|
1099
|
-
`
|
|
1100
|
-
},
|
|
1101
|
-
|
|
1102
|
-
// ----- Interactive -----
|
|
1103
|
-
{
|
|
1104
|
-
file: path.join('resources', 'interactive.md'),
|
|
1105
|
-
fm: {
|
|
1106
|
-
title: 'Interactive Shortcodes', slug: 'interactive',
|
|
1107
|
-
description: 'Live demonstrations of the [slideover] and [dconfig] shortcodes — declarative interactivity without JavaScript.',
|
|
1108
|
-
layout: 'default', status: 'published',
|
|
1109
|
-
sortOrder: 16, showInNav: false, sidebar: false,
|
|
1110
|
-
seo: {
|
|
1111
|
-
title: 'Interactive Shortcodes — Resources',
|
|
1112
|
-
description: 'Live demos of slideover and DConfig in Domma CMS'
|
|
1113
|
-
},
|
|
1114
|
-
createdAt: now, updatedAt: now
|
|
1115
|
-
},
|
|
1116
|
-
body: `# Interactive Shortcodes
|
|
1117
|
-
|
|
1118
|
-
Two shortcodes let you add interactivity to any page without writing JavaScript.
|
|
1119
|
-
|
|
1120
|
-
---
|
|
1121
|
-
|
|
1122
|
-
## Slideover
|
|
1123
|
-
|
|
1124
|
-
[slideover title="More Information" trigger="Read more →"]
|
|
1125
|
-
## About Domma CMS
|
|
1126
|
-
|
|
1127
|
-
Domma CMS is a **file-based** content management system built on Fastify. Pages are stored as Markdown files with YAML frontmatter.
|
|
1128
|
-
|
|
1129
|
-
No database required — content lives in \\\`content/pages/\\\` and is served server-side.
|
|
1130
|
-
[/slideover]
|
|
1131
|
-
|
|
1132
|
-
[slideover title="Package Details" trigger="View specifications" size="lg"]
|
|
1133
|
-
[card title="Technical Requirements"]
|
|
1134
|
-
- **Node.js** 18 or later
|
|
1135
|
-
- Any Linux/macOS/Windows system
|
|
1136
|
-
[/card]
|
|
1137
|
-
|
|
1138
|
-
[card title="Included Plugins" collapsible="true"]
|
|
1139
|
-
- Back to Top
|
|
1140
|
-
- Cookie Consent
|
|
1141
|
-
- Custom CSS
|
|
1142
|
-
- Form Builder
|
|
1143
|
-
[/card]
|
|
1144
|
-
[/slideover]
|
|
1145
|
-
|
|
1146
|
-
---
|
|
1147
|
-
|
|
1148
|
-
## DConfig — Toggle on Click
|
|
1149
|
-
|
|
1150
|
-
[dconfig]
|
|
1151
|
-
{
|
|
1152
|
-
"#toggle-demo-btn": {
|
|
1153
|
-
"events": {
|
|
1154
|
-
"click": { "target": "#toggle-demo-panel", "toggleClass": "hidden" }
|
|
1155
|
-
}
|
|
1156
|
-
}
|
|
1157
|
-
}
|
|
1158
|
-
[/dconfig]
|
|
1159
|
-
|
|
1160
|
-
<button id="toggle-demo-btn" class="btn btn-primary">Toggle panel</button>
|
|
1161
|
-
|
|
1162
|
-
<div id="toggle-demo-panel" class="card mt-3" style="max-width:400px">
|
|
1163
|
-
<div class="card-body">
|
|
1164
|
-
<p>This panel toggles when you click the button above.</p>
|
|
1165
|
-
</div>
|
|
1166
|
-
</div>
|
|
1167
|
-
|
|
1168
|
-
---
|
|
1169
|
-
|
|
1170
|
-
## Syntax Reference
|
|
1171
|
-
|
|
1172
|
-
**Slideover attributes:**
|
|
1173
|
-
|
|
1174
|
-
| Attribute | Default | Description |
|
|
1175
|
-
|-----------|---------|-------------|
|
|
1176
|
-
| \`title\` | — | Panel header text |
|
|
1177
|
-
| \`trigger\` | \`"Open"\` | Button label |
|
|
1178
|
-
| \`size\` | \`"md"\` | \`sm\`, \`md\`, \`lg\` |
|
|
1179
|
-
| \`position\` | \`"right"\` | \`right\` or \`left\` |
|
|
1180
|
-
|
|
1181
|
-
**DConfig format:**
|
|
1182
|
-
|
|
1183
|
-
\`\`\`
|
|
1184
|
-
[dconfig]
|
|
1185
|
-
{
|
|
1186
|
-
"#selector": {
|
|
1187
|
-
"events": {
|
|
1188
|
-
"click": { "target": "#other-selector", "toggleClass": "class-name" }
|
|
1189
|
-
}
|
|
1190
|
-
}
|
|
1191
|
-
}
|
|
1192
|
-
[/dconfig]
|
|
1193
|
-
\`\`\`
|
|
1194
|
-
|
|
1195
|
-
See the [Shortcode Reference](/resources/shortcodes) for full documentation.
|
|
1196
|
-
|
|
1197
|
-
---
|
|
1198
|
-
|
|
1199
|
-
← [Back to Resources](/resources)
|
|
1200
|
-
`
|
|
1201
|
-
},
|
|
1202
|
-
{
|
|
1203
|
-
file: 'privacy.md',
|
|
1204
|
-
fm: {
|
|
1205
|
-
title: 'Privacy Policy', slug: 'privacy',
|
|
1206
|
-
description: 'How we collect, use, and protect your personal data',
|
|
1207
|
-
layout: 'default', status: 'published',
|
|
1208
|
-
sortOrder: 90, showInNav: false, sidebar: false,
|
|
1209
|
-
seo: {title: 'Privacy Policy', description: 'How we collect, use, and protect your personal data'},
|
|
1210
|
-
createdAt: now, updatedAt: now, visibility: 'public'
|
|
1211
|
-
},
|
|
1212
|
-
body: `[hero variant="dark" size="sm" fullwidth="true" twinkle twinkle-count="20" blobs]
|
|
1213
|
-
|
|
1214
|
-
# Privacy Policy
|
|
1215
|
-
|
|
1216
|
-
How [Your Organisation] collects, uses, and protects your personal data.
|
|
1217
|
-
|
|
1218
|
-
[/hero]
|
|
1219
|
-
|
|
1220
|
-
**Last updated: ${new Date().toLocaleDateString('en-GB', {day: 'numeric', month: 'long', year: 'numeric'})}**
|
|
1221
|
-
|
|
1222
|
-
[Your Organisation] ("we", "us", "our") is committed to protecting and respecting your privacy. This policy explains
|
|
1223
|
-
what personal data we collect, how we use it, and your rights under applicable data protection law, including the UK
|
|
1224
|
-
GDPR.
|
|
1225
|
-
|
|
1226
|
-
---
|
|
1227
|
-
|
|
1228
|
-
## 1. Who We Are
|
|
1229
|
-
|
|
1230
|
-
**Data Controller:** [Your Organisation]
|
|
1231
|
-
|
|
1232
|
-
If you have any questions about this policy or how we handle your data, please [contact us](/contact).
|
|
1233
|
-
|
|
1234
|
-
---
|
|
1235
|
-
|
|
1236
|
-
## 2. What Data We Collect
|
|
1237
|
-
|
|
1238
|
-
We may collect and process the following categories of personal data:
|
|
1239
|
-
|
|
1240
|
-
**Information you provide directly:**
|
|
1241
|
-
|
|
1242
|
-
- Name and contact details (e.g. email address) when you submit a contact or feedback form
|
|
1243
|
-
- Any other information you voluntarily provide through the site
|
|
1244
|
-
|
|
1245
|
-
**Information collected automatically:**
|
|
1246
|
-
|
|
1247
|
-
- Server access logs (IP address, browser type, pages visited, timestamps) for security and performance monitoring
|
|
1248
|
-
- Session data stored in your browser (e.g. theme preferences)
|
|
1249
|
-
|
|
1250
|
-
We do not use third-party analytics services or advertising trackers on this site.
|
|
1251
|
-
|
|
1252
|
-
---
|
|
1253
|
-
|
|
1254
|
-
## 3. How We Use Your Data
|
|
1255
|
-
|
|
1256
|
-
We use the personal data we collect for the following purposes:
|
|
1257
|
-
|
|
1258
|
-
| Purpose | Legal Basis |
|
|
1259
|
-
|----------------------------------------------------------|----------------------|
|
|
1260
|
-
| Responding to enquiries submitted via our contact form | Legitimate interests |
|
|
1261
|
-
| Monitoring site security and diagnosing technical issues | Legitimate interests |
|
|
1262
|
-
| Complying with legal obligations | Legal obligation |
|
|
1263
|
-
|
|
1264
|
-
We will never sell, rent, or share your personal data with third parties for marketing purposes.
|
|
1265
|
-
|
|
1266
|
-
---
|
|
1267
|
-
|
|
1268
|
-
## 4. How Long We Keep Your Data
|
|
1269
|
-
|
|
1270
|
-
We retain personal data only for as long as necessary for the purposes described above:
|
|
1271
|
-
|
|
1272
|
-
- **Contact form submissions:** Up to 12 months from the date of receipt, unless an ongoing relationship requires longer
|
|
1273
|
-
retention
|
|
1274
|
-
- **Server access logs:** Up to 30 days, then automatically purged
|
|
1275
|
-
|
|
1276
|
-
---
|
|
1277
|
-
|
|
1278
|
-
## 5. Your Rights
|
|
1279
|
-
|
|
1280
|
-
Under the UK GDPR, you have the following rights regarding your personal data:
|
|
1281
|
-
|
|
1282
|
-
- **Right of access** — request a copy of the data we hold about you
|
|
1283
|
-
- **Right to rectification** — ask us to correct inaccurate data
|
|
1284
|
-
- **Right to erasure** — ask us to delete your data where we have no lawful basis to retain it
|
|
1285
|
-
- **Right to restrict processing** — ask us to pause processing while a dispute is resolved
|
|
1286
|
-
- **Right to data portability** — receive your data in a structured, machine-readable format
|
|
1287
|
-
- **Right to object** — object to processing based on legitimate interests
|
|
1288
|
-
|
|
1289
|
-
To exercise any of these rights, please [contact us](/contact). We will respond within one calendar month.
|
|
1290
|
-
|
|
1291
|
-
If you are not satisfied with our response, you have the right to lodge a complaint with the **Information
|
|
1292
|
-
Commissioner's Office (ICO)**: [ico.org.uk](https://ico.org.uk) | 0303 123 1113.
|
|
1293
|
-
|
|
1294
|
-
---
|
|
1295
|
-
|
|
1296
|
-
## 6. Cookies
|
|
1297
|
-
|
|
1298
|
-
This site uses only essential cookies necessary for its operation (e.g. storing your preferred theme). No tracking or
|
|
1299
|
-
advertising cookies are used. See our [Cookie Policy](/cookies) for full details.
|
|
1300
|
-
|
|
1301
|
-
---
|
|
1302
|
-
|
|
1303
|
-
## 7. Security
|
|
1304
|
-
|
|
1305
|
-
We take appropriate technical and organisational measures to protect your personal data against unauthorised access,
|
|
1306
|
-
disclosure, alteration, or destruction.
|
|
1307
|
-
|
|
1308
|
-
---
|
|
1309
|
-
|
|
1310
|
-
## 8. Changes to This Policy
|
|
1311
|
-
|
|
1312
|
-
We may update this policy from time to time. The "Last updated" date at the top of this page will always reflect the
|
|
1313
|
-
most recent revision.
|
|
1314
|
-
|
|
1315
|
-
---
|
|
1316
|
-
|
|
1317
|
-
## 9. Contact Us
|
|
1318
|
-
|
|
1319
|
-
For any privacy-related enquiries, please use our [contact page](/contact).
|
|
1320
|
-
`
|
|
1321
|
-
},
|
|
1322
|
-
{
|
|
1323
|
-
file: 'cookies.md',
|
|
1324
|
-
fm: {
|
|
1325
|
-
title: 'Cookie Policy', slug: 'cookies',
|
|
1326
|
-
description: 'Our approach to cookies, tracking, and your rights under UK GDPR',
|
|
1327
|
-
layout: 'default', status: 'published',
|
|
1328
|
-
sortOrder: 91, showInNav: false, sidebar: false,
|
|
1329
|
-
seo: {
|
|
1330
|
-
title: 'Cookie Policy',
|
|
1331
|
-
description: 'Our approach to cookies, tracking, and your rights under UK GDPR'
|
|
1332
|
-
},
|
|
1333
|
-
createdAt: now, updatedAt: now, visibility: 'public'
|
|
1334
|
-
},
|
|
1335
|
-
body: `[hero variant="dark" size="sm" fullwidth="true" twinkle twinkle-count="20" blobs]
|
|
1336
|
-
|
|
1337
|
-
# Cookie Policy
|
|
1338
|
-
|
|
1339
|
-
Your rights and our obligations under UK GDPR & PECR.
|
|
1340
|
-
|
|
1341
|
-
[/hero]
|
|
1342
|
-
|
|
1343
|
-
**Last updated: ${new Date().toLocaleDateString('en-GB', {day: 'numeric', month: 'long', year: 'numeric'})}**
|
|
1344
|
-
|
|
1345
|
-
This page explains how [Your Organisation] handles cookies and your rights under the UK General Data Protection
|
|
1346
|
-
Regulation (UK GDPR) and the Privacy and Electronic Communications Regulations (PECR).
|
|
1347
|
-
|
|
1348
|
-
---
|
|
1349
|
-
|
|
1350
|
-
## 1. What Are Cookies?
|
|
1351
|
-
|
|
1352
|
-
Cookies are small text files placed on your device by a website. They allow the site to remember your preferences and
|
|
1353
|
-
settings between visits.
|
|
1354
|
-
|
|
1355
|
-
---
|
|
1356
|
-
|
|
1357
|
-
## 2. Cookies We Use
|
|
1358
|
-
|
|
1359
|
-
This site uses a minimal, privacy-first approach to cookies. We do **not** use advertising, tracking, or profiling
|
|
1360
|
-
cookies of any kind.
|
|
1361
|
-
|
|
1362
|
-
| Cookie | Type | Purpose | Duration |
|
|
1363
|
-
|-------------|------------|---------------------------------------|------------------------|
|
|
1364
|
-
| \`dm_theme\` | Functional | Stores your preferred colour theme | Session / localStorage |
|
|
1365
|
-
| \`dm_motion\` | Functional | Stores your reduced-motion preference | Session / localStorage |
|
|
1366
|
-
|
|
1367
|
-
**Note:** Theme and motion preferences are stored in your browser's \`localStorage\`, not as HTTP cookies. They never
|
|
1368
|
-
leave your device and are not transmitted to our servers.
|
|
1369
|
-
|
|
1370
|
-
We do not embed third-party content (e.g. social media widgets, YouTube iframes) that would set third-party cookies
|
|
1371
|
-
without your consent.
|
|
1372
|
-
|
|
1373
|
-
---
|
|
1374
|
-
|
|
1375
|
-
## 3. Your Cookie Choices
|
|
1376
|
-
|
|
1377
|
-
Because we only use functional, non-tracking storage, we do not require a cookie consent banner under PECR.
|
|
1378
|
-
|
|
1379
|
-
You can clear locally stored preferences at any time through your browser settings:
|
|
1380
|
-
|
|
1381
|
-
- **Chrome / Edge:** Settings → Privacy and security → Clear browsing data → Cookies and other site data
|
|
1382
|
-
- **Firefox:** Settings → Privacy & Security → Cookies and Site Data → Clear Data
|
|
1383
|
-
- **Safari:** Settings → Safari → Clear History and Website Data
|
|
1384
|
-
|
|
1385
|
-
Clearing these will reset your theme and motion preferences to the site defaults.
|
|
1386
|
-
|
|
1387
|
-
---
|
|
1388
|
-
|
|
1389
|
-
## 4. Your Rights Under UK GDPR
|
|
1390
|
-
|
|
1391
|
-
As a UK resident (or EU resident accessing our site), you have rights under UK GDPR:
|
|
1392
|
-
|
|
1393
|
-
### Right to Be Informed
|
|
1394
|
-
|
|
1395
|
-
We tell you how we use your data through this policy and our [Privacy Policy](/privacy).
|
|
1396
|
-
|
|
1397
|
-
### Right of Access
|
|
1398
|
-
|
|
1399
|
-
You can request a copy of any personal data we hold about you by [contacting us](/contact).
|
|
1400
|
-
|
|
1401
|
-
### Right to Erasure ("Right to be Forgotten")
|
|
1402
|
-
|
|
1403
|
-
Where we hold personal data about you and have no overriding legal reason to retain it, you can ask us to delete it.
|
|
1404
|
-
|
|
1405
|
-
### Right to Restrict Processing
|
|
1406
|
-
|
|
1407
|
-
If you dispute the accuracy of your data or our right to process it, you can ask us to pause processing while we
|
|
1408
|
-
investigate.
|
|
1409
|
-
|
|
1410
|
-
### Right to Object
|
|
1411
|
-
|
|
1412
|
-
You can object to processing of your personal data where we rely on legitimate interests as the legal basis.
|
|
1413
|
-
|
|
1414
|
-
### Right to Data Portability
|
|
1415
|
-
|
|
1416
|
-
Where processing is based on your consent or a contract, you can receive your data in a portable format.
|
|
1417
|
-
|
|
1418
|
-
### How to Exercise Your Rights
|
|
1419
|
-
|
|
1420
|
-
Submit a request via our [contact page](/contact). We will acknowledge your request within 72 hours and respond fully
|
|
1421
|
-
within one calendar month.
|
|
1422
|
-
|
|
1423
|
-
---
|
|
1424
|
-
|
|
1425
|
-
## 5. Lawful Bases for Processing
|
|
1426
|
-
|
|
1427
|
-
We only process personal data where we have a valid lawful basis. The primary bases we rely on are:
|
|
1428
|
-
|
|
1429
|
-
- **Legitimate interests** — operating a secure, functional website and responding to enquiries
|
|
1430
|
-
- **Legal obligation** — where required by UK law
|
|
1431
|
-
|
|
1432
|
-
We do not rely on consent for any processing on this site, meaning you do not need to opt in or out for the site to
|
|
1433
|
-
function normally.
|
|
1434
|
-
|
|
1435
|
-
---
|
|
1436
|
-
|
|
1437
|
-
## 6. International Transfers
|
|
1438
|
-
|
|
1439
|
-
All data processed by this site is stored and processed within the UK and/or EEA. We do not transfer personal data to
|
|
1440
|
-
countries outside these territories.
|
|
1441
|
-
|
|
1442
|
-
---
|
|
1443
|
-
|
|
1444
|
-
## 7. Data Retention
|
|
1445
|
-
|
|
1446
|
-
We retain personal data only as long as necessary. See our [Privacy Policy](/privacy) for specific retention periods.
|
|
1447
|
-
|
|
1448
|
-
---
|
|
1449
|
-
|
|
1450
|
-
## 8. The ICO
|
|
1451
|
-
|
|
1452
|
-
The UK supervisory authority for data protection is the **Information Commissioner's Office (ICO)**:
|
|
1453
|
-
|
|
1454
|
-
- Website: [ico.org.uk](https://ico.org.uk)
|
|
1455
|
-
- Phone: 0303 123 1113
|
|
1456
|
-
|
|
1457
|
-
You have the right to lodge a complaint with the ICO at any time if you believe we have not handled your data lawfully.
|
|
1458
|
-
|
|
1459
|
-
---
|
|
1460
|
-
|
|
1461
|
-
## 9. Changes to This Policy
|
|
1462
|
-
|
|
1463
|
-
We will update this page whenever our practices change. The "Last updated" date at the top reflects the current
|
|
1464
|
-
revision.
|
|
1465
|
-
|
|
1466
|
-
---
|
|
1467
|
-
|
|
1468
|
-
## 10. Contact
|
|
1469
|
-
|
|
1470
|
-
Privacy queries: use our [contact page](/contact).
|
|
1471
|
-
`
|
|
1472
|
-
}
|
|
1473
|
-
];
|
|
1474
|
-
|
|
1475
|
-
// ---------------------------------------------------------------------------
|
|
1476
|
-
// Default collections
|
|
1477
|
-
// ---------------------------------------------------------------------------
|
|
1478
|
-
|
|
1479
|
-
const COLLECTIONS = [
|
|
1480
|
-
{
|
|
1481
|
-
slug: 'contacts',
|
|
1482
|
-
schema: {
|
|
1483
|
-
slug: 'contacts',
|
|
1484
|
-
title: 'Contacts',
|
|
1485
|
-
description: 'People and their contact information.',
|
|
1486
|
-
fields: [
|
|
1487
|
-
{name: 'full_name', label: 'Full Name', type: 'text', required: true},
|
|
1488
|
-
{name: 'email_address', label: 'Email', type: 'text', required: true},
|
|
1489
|
-
{name: 'phone_number', label: 'Phone', type: 'text'}
|
|
1490
|
-
],
|
|
1491
|
-
api: {
|
|
1492
|
-
create: {enabled: true, access: 'public'},
|
|
1493
|
-
read: {enabled: true, access: 'admin'},
|
|
1494
|
-
update: {enabled: false, access: 'admin'},
|
|
1495
|
-
delete: {enabled: false, access: 'admin'}
|
|
1496
|
-
}
|
|
1497
|
-
}
|
|
1498
|
-
},
|
|
1499
|
-
{
|
|
1500
|
-
slug: 'enquiries',
|
|
1501
|
-
schema: {
|
|
1502
|
-
slug: 'enquiries',
|
|
1503
|
-
title: 'Enquiries',
|
|
1504
|
-
description: 'Messages and enquiries from website visitors.',
|
|
1505
|
-
fields: [
|
|
1506
|
-
{name: 'full_name', label: 'Full Name', type: 'text', required: true},
|
|
1507
|
-
{name: 'email', label: 'Email', type: 'text', required: true},
|
|
1508
|
-
{name: 'phone', label: 'Phone', type: 'text'},
|
|
1509
|
-
{
|
|
1510
|
-
name: 'subject',
|
|
1511
|
-
label: 'Subject',
|
|
1512
|
-
type: 'select',
|
|
1513
|
-
options: ['General Enquiry', 'Support', 'Sales', 'Partnership', 'Other'],
|
|
1514
|
-
required: true
|
|
1515
|
-
},
|
|
1516
|
-
{name: 'message', label: 'Message', type: 'text', required: true}
|
|
1517
|
-
],
|
|
1518
|
-
api: {
|
|
1519
|
-
create: {enabled: true, access: 'public'},
|
|
1520
|
-
read: {enabled: true, access: 'admin'},
|
|
1521
|
-
update: {enabled: false, access: 'admin'},
|
|
1522
|
-
delete: {enabled: false, access: 'admin'}
|
|
1523
|
-
}
|
|
1524
|
-
}
|
|
1525
|
-
},
|
|
1526
|
-
{
|
|
1527
|
-
slug: 'feedback',
|
|
1528
|
-
schema: {
|
|
1529
|
-
slug: 'feedback',
|
|
1530
|
-
title: 'Feedback',
|
|
1531
|
-
description: 'User feedback and ratings.',
|
|
1532
|
-
fields: [
|
|
1533
|
-
{name: 'name', label: 'Name', type: 'text', required: true},
|
|
1534
|
-
{name: 'email', label: 'Email', type: 'text', required: true},
|
|
1535
|
-
{
|
|
1536
|
-
name: 'rating',
|
|
1537
|
-
label: 'Rating',
|
|
1538
|
-
type: 'select',
|
|
1539
|
-
options: ['Excellent', 'Good', 'Average', 'Poor'],
|
|
1540
|
-
required: true
|
|
1541
|
-
},
|
|
1542
|
-
{
|
|
1543
|
-
name: 'category',
|
|
1544
|
-
label: 'Category',
|
|
1545
|
-
type: 'select',
|
|
1546
|
-
options: ['General', 'Bug Report', 'Feature Request', 'Praise']
|
|
1547
|
-
},
|
|
1548
|
-
{name: 'subject', label: 'Subject', type: 'text'},
|
|
1549
|
-
{name: 'message', label: 'Message', type: 'text', required: true}
|
|
1550
|
-
],
|
|
1551
|
-
api: {
|
|
1552
|
-
create: {enabled: true, access: 'public'},
|
|
1553
|
-
read: {enabled: true, access: 'admin'},
|
|
1554
|
-
update: {enabled: false, access: 'admin'},
|
|
1555
|
-
delete: {enabled: false, access: 'admin'}
|
|
1556
|
-
}
|
|
1557
|
-
}
|
|
1558
|
-
},
|
|
1559
|
-
{
|
|
1560
|
-
slug: 'to-do',
|
|
1561
|
-
schema: {
|
|
1562
|
-
slug: 'to-do',
|
|
1563
|
-
title: 'To-Do',
|
|
1564
|
-
description: 'Task tracking with priorities and due dates.',
|
|
1565
|
-
fields: [
|
|
1566
|
-
{name: 'title', label: 'Title', type: 'text', required: true},
|
|
1567
|
-
{name: 'description', label: 'Description', type: 'text'},
|
|
1568
|
-
{name: 'status', label: 'Status', type: 'select', options: ['Pending', 'In Progress', 'Done'], required: true},
|
|
1569
|
-
{name: 'priority', label: 'Priority', type: 'select', options: ['Low', 'Medium', 'High']},
|
|
1570
|
-
{name: 'due_date', label: 'Due Date', type: 'text'},
|
|
1571
|
-
{name: 'assigned_to', label: 'Assigned To', type: 'text'}
|
|
1572
|
-
],
|
|
1573
|
-
api: {
|
|
1574
|
-
create: {enabled: false, access: 'admin'},
|
|
1575
|
-
read: {enabled: false, access: 'admin'},
|
|
1576
|
-
update: {enabled: false, access: 'admin'},
|
|
1577
|
-
delete: {enabled: false, access: 'admin'}
|
|
1578
|
-
}
|
|
1579
|
-
}
|
|
1580
|
-
},
|
|
1581
|
-
{
|
|
1582
|
-
slug: 'notes',
|
|
1583
|
-
schema: {
|
|
1584
|
-
slug: 'notes',
|
|
1585
|
-
title: 'Notes',
|
|
1586
|
-
description: 'Free-form notes with categories and tags.',
|
|
1587
|
-
fields: [
|
|
1588
|
-
{name: 'title', label: 'Title', type: 'text', required: true},
|
|
1589
|
-
{name: 'content', label: 'Content', type: 'text', required: true},
|
|
1590
|
-
{name: 'category', label: 'Category', type: 'select', options: ['General', 'Idea', 'Reminder', 'Reference']},
|
|
1591
|
-
{name: 'tags', label: 'Tags', type: 'text'}
|
|
1592
|
-
],
|
|
1593
|
-
api: {
|
|
1594
|
-
create: {enabled: false, access: 'admin'},
|
|
1595
|
-
read: {enabled: false, access: 'admin'},
|
|
1596
|
-
update: {enabled: false, access: 'admin'},
|
|
1597
|
-
delete: {enabled: false, access: 'admin'}
|
|
1598
|
-
}
|
|
1599
|
-
}
|
|
1600
|
-
}
|
|
1601
|
-
];
|
|
1602
|
-
|
|
1603
|
-
// ---------------------------------------------------------------------------
|
|
1604
|
-
// Default forms (with collection actions)
|
|
1605
|
-
// ---------------------------------------------------------------------------
|
|
1606
|
-
|
|
1607
|
-
const FORMS = [
|
|
1608
|
-
{
|
|
1609
|
-
slug: 'contacts',
|
|
1610
|
-
data: {
|
|
1611
|
-
slug: 'contacts',
|
|
1612
|
-
title: 'Contacts',
|
|
1613
|
-
description: 'Contact Information',
|
|
1614
|
-
fields: [
|
|
1615
|
-
{
|
|
1616
|
-
name: 'full_name',
|
|
1617
|
-
type: 'string',
|
|
1618
|
-
label: 'Full Name',
|
|
1619
|
-
required: false,
|
|
1620
|
-
placeholder: 'Full Name',
|
|
1621
|
-
helper: 'Full Name',
|
|
1622
|
-
minLength: 8,
|
|
1623
|
-
maxLength: 255
|
|
1624
|
-
},
|
|
1625
|
-
{type: 'spacer'},
|
|
1626
|
-
{
|
|
1627
|
-
name: 'phone_number',
|
|
1628
|
-
type: 'tel',
|
|
1629
|
-
label: 'Phone Number',
|
|
1630
|
-
required: false,
|
|
1631
|
-
placeholder: 'Phone Number',
|
|
1632
|
-
helper: 'Primary Phone Number'
|
|
1633
|
-
},
|
|
1634
|
-
{type: 'spacer'},
|
|
1635
|
-
{
|
|
1636
|
-
name: 'email_address',
|
|
1637
|
-
type: 'string',
|
|
1638
|
-
label: 'Email Address',
|
|
1639
|
-
required: false,
|
|
1640
|
-
placeholder: 'Email Address',
|
|
1641
|
-
helper: 'Email Address',
|
|
1642
|
-
minLength: 8,
|
|
1643
|
-
maxLength: 255
|
|
1644
|
-
}
|
|
1645
|
-
],
|
|
1646
|
-
settings: {
|
|
1647
|
-
submitText: 'Submit',
|
|
1648
|
-
successMessage: 'Thank you for your submission.',
|
|
1649
|
-
layout: 'stacked',
|
|
1650
|
-
honeypot: true,
|
|
1651
|
-
rateLimitPerMinute: 3
|
|
1652
|
-
},
|
|
1653
|
-
actions: {
|
|
1654
|
-
email: {enabled: false, recipients: '', subjectPrefix: '[Contacts]'},
|
|
1655
|
-
webhook: {enabled: false, url: '', method: 'POST'},
|
|
1656
|
-
collection: {enabled: true, slug: 'contacts'}
|
|
1657
|
-
},
|
|
1658
|
-
createdAt: now,
|
|
1659
|
-
updatedAt: now
|
|
1660
|
-
}
|
|
1661
|
-
},
|
|
1662
|
-
{
|
|
1663
|
-
slug: 'enquiries',
|
|
1664
|
-
data: {
|
|
1665
|
-
slug: 'enquiries',
|
|
1666
|
-
title: 'Enquiries',
|
|
1667
|
-
description: 'Get in touch with us',
|
|
1668
|
-
fields: [
|
|
1669
|
-
{
|
|
1670
|
-
name: 'full_name',
|
|
1671
|
-
type: 'string',
|
|
1672
|
-
label: 'Full Name',
|
|
1673
|
-
required: true,
|
|
1674
|
-
placeholder: 'Your full name',
|
|
1675
|
-
helper: '',
|
|
1676
|
-
validation: {min: 2, max: 100}
|
|
1677
|
-
},
|
|
1678
|
-
{
|
|
1679
|
-
name: 'email',
|
|
1680
|
-
type: 'email',
|
|
1681
|
-
label: 'Email Address',
|
|
1682
|
-
required: true,
|
|
1683
|
-
placeholder: 'your@email.com',
|
|
1684
|
-
helper: ''
|
|
1685
|
-
},
|
|
1686
|
-
{
|
|
1687
|
-
name: 'phone',
|
|
1688
|
-
type: 'tel',
|
|
1689
|
-
label: 'Phone Number',
|
|
1690
|
-
required: false,
|
|
1691
|
-
placeholder: '+44 7700 000000',
|
|
1692
|
-
helper: 'Optional'
|
|
1693
|
-
},
|
|
1694
|
-
{
|
|
1695
|
-
name: 'subject',
|
|
1696
|
-
type: 'select',
|
|
1697
|
-
label: 'Subject',
|
|
1698
|
-
required: true,
|
|
1699
|
-
placeholder: 'Please select a subject',
|
|
1700
|
-
helper: '',
|
|
1701
|
-
options: [
|
|
1702
|
-
{value: 'general', label: 'General Enquiry'},
|
|
1703
|
-
{value: 'support', label: 'Support'},
|
|
1704
|
-
{value: 'sales', label: 'Sales'},
|
|
1705
|
-
{value: 'partnership', label: 'Partnership'},
|
|
1706
|
-
{value: 'other', label: 'Other'}
|
|
1707
|
-
]
|
|
1708
|
-
},
|
|
1709
|
-
{
|
|
1710
|
-
name: 'message',
|
|
1711
|
-
type: 'textarea',
|
|
1712
|
-
label: 'Message',
|
|
1713
|
-
required: true,
|
|
1714
|
-
placeholder: 'How can we help you?',
|
|
1715
|
-
helper: '',
|
|
1716
|
-
rows: 4,
|
|
1717
|
-
validation: {min: 10, max: 2000}
|
|
1718
|
-
}
|
|
1719
|
-
],
|
|
1720
|
-
settings: {
|
|
1721
|
-
submitText: 'Send Message',
|
|
1722
|
-
successMessage: 'Thanks for reaching out! We\'ll get back to you shortly.',
|
|
1723
|
-
layout: 'stacked',
|
|
1724
|
-
honeypot: true,
|
|
1725
|
-
rateLimitPerMinute: 3
|
|
1726
|
-
},
|
|
1727
|
-
actions: {
|
|
1728
|
-
email: {enabled: false, recipients: '', subjectPrefix: '[enquiries]'},
|
|
1729
|
-
webhook: {enabled: false, url: '', method: 'POST'},
|
|
1730
|
-
collection: {enabled: true, slug: 'enquiries'}
|
|
1731
|
-
},
|
|
1732
|
-
createdAt: now,
|
|
1733
|
-
updatedAt: now
|
|
1734
|
-
}
|
|
1735
|
-
},
|
|
1736
|
-
{
|
|
1737
|
-
slug: 'feedback',
|
|
1738
|
-
data: {
|
|
1739
|
-
slug: 'feedback',
|
|
1740
|
-
title: 'Feedback',
|
|
1741
|
-
description: 'Share your feedback with us',
|
|
1742
|
-
fields: [
|
|
1743
|
-
{
|
|
1744
|
-
name: 'name',
|
|
1745
|
-
type: 'string',
|
|
1746
|
-
label: 'Your Name',
|
|
1747
|
-
required: true,
|
|
1748
|
-
placeholder: 'Please enter your full name',
|
|
1749
|
-
helper: 'Please enter your full name',
|
|
1750
|
-
validation: {min: 2, max: 100}
|
|
1751
|
-
},
|
|
1752
|
-
{
|
|
1753
|
-
name: 'email',
|
|
1754
|
-
type: 'email',
|
|
1755
|
-
label: 'Email Address',
|
|
1756
|
-
required: true,
|
|
1757
|
-
placeholder: 'your@email.com',
|
|
1758
|
-
helper: 'Please enter your email address'
|
|
1759
|
-
},
|
|
1760
|
-
{
|
|
1761
|
-
name: 'rating', type: 'select', label: 'Overall Rating', required: true, helper: 'Tell us how we are doing!',
|
|
1762
|
-
options: [
|
|
1763
|
-
{value: 'none', label: 'Please Choose'},
|
|
1764
|
-
{value: 'excellent', label: 'Excellent'},
|
|
1765
|
-
{value: 'good', label: 'Good'},
|
|
1766
|
-
{value: 'average', label: 'Average'},
|
|
1767
|
-
{value: 'poor', label: 'Poor'}
|
|
1768
|
-
]
|
|
1769
|
-
},
|
|
1770
|
-
{
|
|
1771
|
-
name: 'category',
|
|
1772
|
-
type: 'select',
|
|
1773
|
-
label: 'Category',
|
|
1774
|
-
required: true,
|
|
1775
|
-
placeholder: 'Please select a category',
|
|
1776
|
-
helper: '',
|
|
1777
|
-
options: [
|
|
1778
|
-
{value: 'general', label: 'General'},
|
|
1779
|
-
{value: 'bug-report', label: 'Bug Report'},
|
|
1780
|
-
{value: 'feature-request', label: 'Feature Request'},
|
|
1781
|
-
{value: 'praise', label: 'Praise'}
|
|
1782
|
-
]
|
|
1783
|
-
},
|
|
1784
|
-
{
|
|
1785
|
-
name: 'subject',
|
|
1786
|
-
type: 'string',
|
|
1787
|
-
label: 'Subject',
|
|
1788
|
-
required: true,
|
|
1789
|
-
placeholder: 'Brief summary of your feedback',
|
|
1790
|
-
helper: '',
|
|
1791
|
-
validation: {max: 200}
|
|
1792
|
-
},
|
|
1793
|
-
{
|
|
1794
|
-
name: 'message',
|
|
1795
|
-
type: 'textarea',
|
|
1796
|
-
label: 'Your Feedback',
|
|
1797
|
-
required: true,
|
|
1798
|
-
placeholder: 'Please share your thoughts in detail…',
|
|
1799
|
-
helper: 'Please share your thoughts in detail…',
|
|
1800
|
-
rows: 4,
|
|
1801
|
-
validation: {min: 10, max: 2000}
|
|
1802
|
-
}
|
|
1803
|
-
],
|
|
1804
|
-
settings: {
|
|
1805
|
-
submitText: 'Submit Feedback',
|
|
1806
|
-
successMessage: 'Thank you for your feedback! We appreciate you taking the time.',
|
|
1807
|
-
layout: 'stacked',
|
|
1808
|
-
honeypot: true,
|
|
1809
|
-
rateLimitPerMinute: 3
|
|
1810
|
-
},
|
|
1811
|
-
actions: {
|
|
1812
|
-
email: {enabled: true, recipients: '', subjectPrefix: '[feedback]'},
|
|
1813
|
-
webhook: {enabled: false, url: '', method: 'POST'},
|
|
1814
|
-
collection: {enabled: true, slug: 'feedback'}
|
|
1815
|
-
},
|
|
1816
|
-
createdAt: now,
|
|
1817
|
-
updatedAt: now
|
|
1818
|
-
}
|
|
1819
|
-
},
|
|
1820
|
-
{
|
|
1821
|
-
slug: 'to-do',
|
|
1822
|
-
data: {
|
|
1823
|
-
slug: 'to-do',
|
|
1824
|
-
title: 'To-Do',
|
|
1825
|
-
description: 'Task tracking with status, priority, and due dates.',
|
|
1826
|
-
fields: [
|
|
1827
|
-
{name: 'title', type: 'string', label: 'Title', required: true, placeholder: 'Task title'},
|
|
1828
|
-
{
|
|
1829
|
-
name: 'description',
|
|
1830
|
-
type: 'textarea',
|
|
1831
|
-
label: 'Description',
|
|
1832
|
-
required: false,
|
|
1833
|
-
placeholder: 'Task details…',
|
|
1834
|
-
rows: 3
|
|
1835
|
-
},
|
|
1836
|
-
{
|
|
1837
|
-
name: 'status', type: 'select', label: 'Status', required: true,
|
|
1838
|
-
options: [
|
|
1839
|
-
{value: 'pending', label: 'Pending'},
|
|
1840
|
-
{value: 'in-progress', label: 'In Progress'},
|
|
1841
|
-
{value: 'done', label: 'Done'}
|
|
1842
|
-
]
|
|
1843
|
-
},
|
|
1844
|
-
{
|
|
1845
|
-
name: 'priority', type: 'select', label: 'Priority', required: false,
|
|
1846
|
-
options: [
|
|
1847
|
-
{value: 'low', label: 'Low'},
|
|
1848
|
-
{value: 'medium', label: 'Medium'},
|
|
1849
|
-
{value: 'high', label: 'High'}
|
|
1850
|
-
]
|
|
1851
|
-
},
|
|
1852
|
-
{name: 'due_date', type: 'date', label: 'Due Date', required: false},
|
|
1853
|
-
{name: 'assigned_to', type: 'string', label: 'Assigned To', required: false, placeholder: 'Name or email'}
|
|
1854
|
-
],
|
|
1855
|
-
settings: {
|
|
1856
|
-
submitText: 'Add Task',
|
|
1857
|
-
successMessage: 'Task added successfully.',
|
|
1858
|
-
layout: 'stacked',
|
|
1859
|
-
honeypot: true,
|
|
1860
|
-
rateLimitPerMinute: 3
|
|
1861
|
-
},
|
|
1862
|
-
actions: {
|
|
1863
|
-
email: {enabled: false, recipients: '', subjectPrefix: '[to-do]'},
|
|
1864
|
-
webhook: {enabled: false, url: '', method: 'POST'},
|
|
1865
|
-
collection: {enabled: true, slug: 'to-do'}
|
|
1866
|
-
},
|
|
1867
|
-
createdAt: now,
|
|
1868
|
-
updatedAt: now
|
|
1869
|
-
}
|
|
1870
|
-
},
|
|
1871
|
-
{
|
|
1872
|
-
slug: 'notes',
|
|
1873
|
-
data: {
|
|
1874
|
-
slug: 'notes',
|
|
1875
|
-
title: 'Notes',
|
|
1876
|
-
description: 'Free-form notes with categories and tags.',
|
|
1877
|
-
fields: [
|
|
1878
|
-
{name: 'title', type: 'string', label: 'Title', required: true, placeholder: 'Note title'},
|
|
1879
|
-
{
|
|
1880
|
-
name: 'content',
|
|
1881
|
-
type: 'textarea',
|
|
1882
|
-
label: 'Content',
|
|
1883
|
-
required: true,
|
|
1884
|
-
placeholder: 'Write your note here…',
|
|
1885
|
-
rows: 5
|
|
1886
|
-
},
|
|
1887
|
-
{
|
|
1888
|
-
name: 'category', type: 'select', label: 'Category', required: false,
|
|
1889
|
-
options: [
|
|
1890
|
-
{value: 'general', label: 'General'},
|
|
1891
|
-
{value: 'idea', label: 'Idea'},
|
|
1892
|
-
{value: 'reminder', label: 'Reminder'},
|
|
1893
|
-
{value: 'reference', label: 'Reference'}
|
|
1894
|
-
]
|
|
1895
|
-
},
|
|
1896
|
-
{
|
|
1897
|
-
name: 'tags',
|
|
1898
|
-
type: 'string',
|
|
1899
|
-
label: 'Tags',
|
|
1900
|
-
required: false,
|
|
1901
|
-
placeholder: 'Comma-separated tags',
|
|
1902
|
-
helper: 'Separate tags with commas'
|
|
1903
|
-
}
|
|
1904
|
-
],
|
|
1905
|
-
settings: {
|
|
1906
|
-
submitText: 'Save Note',
|
|
1907
|
-
successMessage: 'Note saved successfully.',
|
|
1908
|
-
layout: 'stacked',
|
|
1909
|
-
honeypot: true,
|
|
1910
|
-
rateLimitPerMinute: 3
|
|
1911
|
-
},
|
|
1912
|
-
actions: {
|
|
1913
|
-
email: {enabled: false, recipients: '', subjectPrefix: '[notes]'},
|
|
1914
|
-
webhook: {enabled: false, url: '', method: 'POST'},
|
|
1915
|
-
collection: {enabled: true, slug: 'notes'}
|
|
1916
|
-
},
|
|
1917
|
-
createdAt: now,
|
|
1918
|
-
updatedAt: now
|
|
1919
|
-
}
|
|
1920
|
-
}
|
|
1921
|
-
];
|
|
1922
|
-
|
|
1923
|
-
// ---------------------------------------------------------------------------
|
|
1924
|
-
// Serialise frontmatter + body to .md string
|
|
1925
|
-
// Produces the same YAML-frontmatter format gray-matter reads.
|
|
1926
|
-
// ---------------------------------------------------------------------------
|
|
1927
|
-
|
|
1928
|
-
function toMarkdown(fm, body) {
|
|
1929
|
-
const lines = [];
|
|
1930
|
-
for (const [k, v] of Object.entries(fm)) {
|
|
1931
|
-
if (v !== null && typeof v === 'object' && !Array.isArray(v)) {
|
|
1932
|
-
lines.push(`${k}:`);
|
|
1933
|
-
for (const [nk, nv] of Object.entries(v)) {
|
|
1934
|
-
lines.push(` ${nk}: ${JSON.stringify(nv)}`);
|
|
1935
|
-
}
|
|
1936
|
-
} else {
|
|
1937
|
-
lines.push(`${k}: ${JSON.stringify(v)}`);
|
|
1938
|
-
}
|
|
1939
|
-
}
|
|
1940
|
-
return `---\n${lines.join('\n')}\n---\n\n${body}`;
|
|
1941
|
-
}
|
|
1942
|
-
|
|
1943
|
-
// ---------------------------------------------------------------------------
|
|
1944
|
-
// Main
|
|
1945
|
-
// ---------------------------------------------------------------------------
|
|
1946
|
-
|
|
1947
|
-
console.log('');
|
|
1948
|
-
console.log(' ┌──────────────────────────────────┐');
|
|
1949
|
-
console.log(' │ Domma CMS — Seed Demo Content │');
|
|
1950
|
-
console.log(' └──────────────────────────────────┘');
|
|
1951
|
-
console.log('');
|
|
1952
|
-
|
|
1953
|
-
for (const page of PAGES) {
|
|
1954
|
-
const filePath = path.join(PAGES_DIR, page.file);
|
|
1955
|
-
await mkdir(path.dirname(filePath), { recursive: true });
|
|
1956
|
-
await writeFile(filePath, toMarkdown(page.fm, page.body), 'utf8');
|
|
1957
|
-
const urlLabel = '/' + page.file.replace(/\\/g, '/').replace(/index\.md$/, '').replace(/\.md$/, '');
|
|
1958
|
-
console.log(` ✓ ${urlLabel || '/'}`);
|
|
1959
|
-
}
|
|
1960
|
-
|
|
1961
|
-
process.stdout.write(' Updating navigation…');
|
|
1962
|
-
await writeFile(NAV_CFG, JSON.stringify(SEED_NAV, null, 4) + '\n', 'utf8');
|
|
1963
|
-
console.log(' done.');
|
|
1964
|
-
|
|
1965
|
-
for (const col of COLLECTIONS) {
|
|
1966
|
-
const dir = path.join(COLLECTIONS_DIR, col.slug);
|
|
1967
|
-
await mkdir(dir, {recursive: true});
|
|
1968
|
-
await writeFile(path.join(dir, 'schema.json'), JSON.stringify(col.schema, null, 2) + '\n', 'utf8');
|
|
1969
|
-
// Only initialise data.json if it doesn't already exist (preserve entries)
|
|
1970
|
-
const dataFile = path.join(dir, 'data.json');
|
|
1971
|
-
try {
|
|
1972
|
-
await writeFile(dataFile, '[]\n', {encoding: 'utf8', flag: 'wx'});
|
|
1973
|
-
} catch { /* already exists */
|
|
1974
|
-
}
|
|
1975
|
-
console.log(` ✓ collection: ${col.slug}`);
|
|
1976
|
-
}
|
|
1977
|
-
|
|
1978
|
-
await mkdir(FORMS_DIR, {recursive: true});
|
|
1979
|
-
await mkdir(SUBS_DIR, {recursive: true});
|
|
1980
|
-
for (const form of FORMS) {
|
|
1981
|
-
await writeFile(path.join(FORMS_DIR, `${form.slug}.json`), JSON.stringify(form.data, null, 4) + '\n', 'utf8');
|
|
1982
|
-
// Only initialise submissions file if it doesn't already exist
|
|
1983
|
-
const subsFile = path.join(SUBS_DIR, `${form.slug}.json`);
|
|
1984
|
-
try {
|
|
1985
|
-
await writeFile(subsFile, '[]\n', {encoding: 'utf8', flag: 'wx'});
|
|
1986
|
-
} catch { /* already exists */
|
|
1987
|
-
}
|
|
1988
|
-
const colSlug = form.data.actions?.collection?.slug ?? '—';
|
|
1989
|
-
console.log(` ✓ form: ${form.slug} → collection: ${colSlug}`);
|
|
1990
|
-
}
|
|
1991
|
-
|
|
1992
|
-
console.log('');
|
|
1993
|
-
console.log(` ✓ Seed complete — ${PAGES.length} pages, ${COLLECTIONS.length} collection(s), ${FORMS.length} form(s).`);
|
|
1994
|
-
console.log(' Visit your site at http://localhost:4096/');
|
|
1995
|
-
console.log(' Resources section available at http://localhost:4096/resources');
|
|
1996
|
-
console.log('');
|