domma-cms 0.92.1 → 0.94.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 +5 -3
- package/admin/css/admin.css +1 -1
- package/admin/js/app.js +2 -2
- package/admin/js/lib/action-editor-arrange.js +1 -1
- package/admin/js/lib/api-tokens-arrange.js +2 -2
- package/admin/js/lib/block-editor-arrange.js +1 -1
- package/admin/js/lib/blocks-arrange.js +1 -1
- package/admin/js/lib/collection-entries-arrange.js +1 -1
- package/admin/js/lib/components-arrange.js +1 -1
- package/admin/js/lib/dashboard-arrange.js +1 -1
- package/admin/js/lib/dates.js +1 -0
- package/admin/js/lib/forms-arrange.js +1 -1
- package/admin/js/lib/media-arrange.js +1 -1
- package/admin/js/lib/notifications-arrange.js +1 -1
- package/admin/js/lib/pages-arrange.js +1 -1
- package/admin/js/lib/related.js +1 -1
- package/admin/js/lib/timeline-builder.js +2 -2
- package/admin/js/templates/action-editor.html +6 -5
- package/admin/js/templates/actions-list.html +1 -1
- package/admin/js/templates/contacts.html +1 -1
- package/admin/js/templates/docs/api-actions.html +86 -60
- package/admin/js/templates/docs/api-authentication.html +159 -123
- package/admin/js/templates/docs/api-builder.html +197 -0
- package/admin/js/templates/docs/api-collections.html +199 -259
- package/admin/js/templates/docs/api-external.html +225 -0
- package/admin/js/templates/docs/api-forms.html +268 -0
- package/admin/js/templates/docs/api-layouts.html +70 -45
- package/admin/js/templates/docs/api-media.html +57 -80
- package/admin/js/templates/docs/api-navigation.html +66 -22
- package/admin/js/templates/docs/api-pages.html +109 -129
- package/admin/js/templates/docs/api-plugins.html +123 -61
- package/admin/js/templates/docs/api-scaffold.html +185 -0
- package/admin/js/templates/docs/api-settings.html +72 -64
- package/admin/js/templates/docs/api-users.html +74 -107
- package/admin/js/templates/docs/api-views.html +68 -54
- package/admin/js/templates/docs/components-howto.html +20 -17
- package/admin/js/templates/docs/components-reference.html +13 -16
- package/admin/js/templates/docs/components-rules.html +7 -6
- package/admin/js/templates/docs/components-walkthrough.html +19 -19
- package/admin/js/templates/docs/tutorial-crud.html +71 -40
- package/admin/js/templates/docs/tutorial-forms.html +51 -35
- package/admin/js/templates/docs/tutorial-plugin.html +132 -56
- package/admin/js/templates/docs/usage-actions.html +61 -15
- package/admin/js/templates/docs/usage-collections.html +108 -0
- package/admin/js/templates/docs/usage-cta-shortcode.html +14 -3
- package/admin/js/templates/docs/usage-dconfig.html +0 -3
- package/admin/js/templates/docs/usage-editions.html +213 -0
- package/admin/js/templates/docs/usage-media.html +22 -6
- package/admin/js/templates/docs/usage-navigation.html +74 -18
- package/admin/js/templates/docs/usage-pages.html +60 -20
- package/admin/js/templates/docs/usage-plugins.html +89 -17
- package/admin/js/templates/docs/usage-shortcodes.html +123 -70
- package/admin/js/templates/docs/usage-site-settings.html +50 -18
- package/admin/js/templates/docs/usage-tools.html +73 -0
- package/admin/js/templates/docs/usage-users-roles.html +99 -20
- package/admin/js/templates/docs/usage-views.html +36 -19
- package/admin/js/templates/documentation.html +153 -32
- package/admin/js/templates/page-editor.html +0 -5
- package/admin/js/templates/plugin-guide.html +15 -0
- package/admin/js/templates/plugin-guides.html +21 -0
- package/admin/js/templates/pro-docs.html +53 -234
- package/admin/js/templates/tutorials.html +5 -4
- package/admin/js/views/actions-list.js +3 -3
- package/admin/js/views/analytics.js +5 -5
- package/admin/js/views/api-endpoint-editor.js +2 -2
- package/admin/js/views/block-editor.js +4 -4
- package/admin/js/views/blocks.js +4 -4
- package/admin/js/views/collection-editor.js +4 -4
- package/admin/js/views/collection-entries.js +7 -7
- package/admin/js/views/component-editor.js +2 -2
- package/admin/js/views/contacts.js +22 -20
- package/admin/js/views/context-menu-editor.js +5 -5
- package/admin/js/views/doc-pages.js +1 -1
- package/admin/js/views/form-editor.js +4 -4
- package/admin/js/views/form-submissions.js +2 -2
- package/admin/js/views/index.js +1 -1
- package/admin/js/views/media.js +3 -3
- package/admin/js/views/menu-editor.js +13 -13
- package/admin/js/views/menu-locations.js +2 -2
- package/admin/js/views/my-profile.js +1 -1
- package/admin/js/views/page-editor.js +8 -8
- package/admin/js/views/plugin-guides.js +5 -0
- package/admin/js/views/project-detail.js +2 -2
- package/admin/js/views/project-settings.js +1 -1
- package/admin/js/views/role-editor.js +4 -4
- package/admin/js/views/search.js +2 -2
- package/admin/js/views/seo.js +17 -17
- package/admin/js/views/settings.js +3 -3
- package/admin/js/views/theme.js +3 -3
- package/admin/js/views/user-editor.js +1 -1
- package/admin/js/views/users.js +2 -2
- package/admin/js/views/view-editor.js +1 -1
- package/bin/cli.js +13 -13
- package/bin/lib/node-version.js +29 -0
- package/package.json +1 -1
- package/plugins/_lib/admin/mail/compose-window.js +3 -2
- package/plugins/_lib/admin/mail/reader-view.js +7 -6
- package/plugins/_lib/admin/mail/scheduling.js +4 -2
- package/plugins/_lib/admin/mail/templates.js +4 -4
- package/plugins/_lib/admin/ui/dates.js +85 -0
- package/plugins/blog/CLAUDE.md +31 -22
- package/plugins/blog/admin/views/blog.js +3 -2
- package/plugins/blog/admin/views/comments.js +2 -1
- package/plugins/blog/admin/views/post-editor.js +4 -4
- package/plugins/blog/blocks/blog-card-row.html +1 -1
- package/plugins/blog/blocks/blog-card.html +2 -2
- package/plugins/blog/blocks/blog-post-classic.html +2 -2
- package/plugins/blog/blocks/blog-post-essay.html +2 -2
- package/plugins/blog/blocks/blog-post-feature.html +2 -2
- package/plugins/blog/blocks/blog-post-minimal.html +2 -2
- package/plugins/blog/blocks/blog-post-sidebar.html +2 -2
- package/plugins/blog/blocks/blog-post-split.html +2 -2
- package/plugins/blog/docs/guide.md +205 -0
- package/plugins/blog/lib/layouts.js +3 -3
- package/plugins/blog/lib/page.js +2 -1
- package/plugins/blog/plugin.js +3 -3
- package/plugins/blog/plugin.json +4 -4
- package/plugins/blog/tests/layouts.test.js +6 -0
- package/plugins/feedback/CLAUDE.md +22 -3
- package/plugins/feedback/admin/lib/kit.js +6 -7
- package/plugins/feedback/admin/views/feedback.js +79 -10
- package/plugins/feedback/admin/views/send.js +28 -6
- package/plugins/feedback/docs/guide.md +95 -0
- package/plugins/feedback/lib/receiver.js +9 -2
- package/plugins/feedback/lib/sender.js +3 -2
- package/plugins/feedback/plugin.js +54 -6
- package/plugins/feedback/plugin.json +4 -4
- package/plugins/feedback/tests/api.test.js +74 -2
- package/plugins/free-tier.lock.json +49 -44
- package/plugins/mail-reader/CLAUDE.md +33 -18
- package/plugins/mail-reader/docs/guide.md +147 -0
- package/plugins/mail-reader/plugin.json +1 -1
- package/plugins/security/CLAUDE.md +4 -1
- package/plugins/security/admin/views/security.js +5 -5
- package/plugins/security/docs/guide.md +170 -0
- package/plugins/security/plugin.js +2 -1
- package/plugins/security/plugin.json +2 -1
- package/plugins/shopping-cart/CLAUDE.md +7 -1
- package/plugins/shopping-cart/admin/lib/kit.js +5 -2
- package/plugins/shopping-cart/admin/views/orders.js +4 -4
- package/plugins/shopping-cart/admin/views/overview.js +2 -2
- package/plugins/shopping-cart/docs/guide.md +191 -0
- package/plugins/shopping-cart/lib/render.js +2 -1
- package/plugins/shopping-cart/plugin.json +3 -3
- package/public/js/collection-browser.js +2 -2
- package/public/js/site.js +1 -1
- package/scripts/gen-instance-secret.js +3 -1
- package/scripts/setup.js +3 -1
- package/server/middleware/auth.js +2 -1
- package/server/routes/api/actions.js +47 -27
- package/server/routes/api/blocks.js +2 -1
- package/server/routes/api/collections.js +16 -52
- package/server/routes/api/contacts.js +66 -3
- package/server/routes/api/documentation.js +42 -0
- package/server/routes/api/notifications.js +3 -2
- package/server/routes/api/users.js +10 -6
- package/server/server.js +16 -1
- package/server/services/actions.js +110 -34
- package/server/services/adapterRegistry.js +169 -16
- package/server/services/adapters/FileAdapter.js +25 -0
- package/server/services/adapters/MongoAdapter.js +23 -0
- package/server/services/collections.js +104 -1
- package/server/services/connectionManager.js +12 -0
- package/server/services/dates.js +81 -0
- package/server/services/docs.js +13 -2
- package/server/services/markdown.js +75 -26
- package/server/services/notification-sources.js +6 -5
- package/server/services/passwordReset.js +2 -1
- package/server/services/permissionRegistry.js +3 -2
- package/server/services/pluginGuides.js +255 -0
- package/server/services/pluginInstaller.js +54 -13
- package/server/services/plugins.js +29 -1
- package/server/services/presetCollections.js +31 -5
- package/server/services/renderer.js +2 -2
- package/server/services/sidebarBadges.js +3 -1
- package/server/services/tools.js +4 -2
- package/server/templates/page.html +2 -2
|
@@ -69,89 +69,66 @@
|
|
|
69
69
|
<div class="col-12">
|
|
70
70
|
<div class="docs-body">
|
|
71
71
|
|
|
72
|
+
<p>Media files live in <code>content/media/</code> and are served publicly at <code>/media/<name></code>. The
|
|
73
|
+
endpoints need the <code>media</code> permission for the action named (read, create, update, delete).</p>
|
|
74
|
+
|
|
72
75
|
<h3><span class="method-badge method-get">GET</span><span class="endpoint-path">/api/media</span></h3>
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
[ { "name": "hero.jpg", "url": "/media/hero.jpg", "size": 204800, "
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
<p class="auth-note">Requires Bearer token + <code>media</code> permission.</p>
|
|
127
|
-
<p>Apply image transformations (resize, crop, rotate, watermark, etc.) and optionally save to a new
|
|
128
|
-
filename.</p>
|
|
129
|
-
<table class="table table-sm">
|
|
130
|
-
<thead>
|
|
131
|
-
<tr>
|
|
132
|
-
<th>Field</th>
|
|
133
|
-
<th>Type</th>
|
|
134
|
-
<th>Description</th>
|
|
135
|
-
</tr>
|
|
136
|
-
</thead>
|
|
137
|
-
<tbody>
|
|
138
|
-
<tr>
|
|
139
|
-
<td><code>operations</code></td>
|
|
140
|
-
<td>object</td>
|
|
141
|
-
<td>Transformation operations to apply</td>
|
|
142
|
-
</tr>
|
|
143
|
-
<tr>
|
|
144
|
-
<td><code>saveAs</code></td>
|
|
145
|
-
<td>string</td>
|
|
146
|
-
<td>Optional. Output filename. Defaults to overwriting the source.</td>
|
|
147
|
-
</tr>
|
|
148
|
-
</tbody>
|
|
149
|
-
</table>
|
|
150
|
-
<pre class="code-block"><code>// Request body
|
|
76
|
+
<p class="auth-note">Requires Bearer token + <code>media</code> read permission.</p>
|
|
77
|
+
<p>Every file in the library, newest first.</p>
|
|
78
|
+
<pre class="code-block"><code>// Response 200
|
|
79
|
+
[ { "name": "hero.jpg", "url": "/media/hero.jpg", "size": 204800, "createdAt": "2026-09-27T10:30:00.000Z" } ]</code></pre>
|
|
80
|
+
|
|
81
|
+
<h3><span class="method-badge method-post">POST</span><span class="endpoint-path">/api/media</span></h3>
|
|
82
|
+
<p class="auth-note">Requires Bearer token + <code>media</code> create permission. Content-Type:
|
|
83
|
+
<code>multipart/form-data</code>.</p>
|
|
84
|
+
<p>Upload one or more files. Names are made safe and may be at most 200 characters. Images (JPEG, PNG, GIF, WebP,
|
|
85
|
+
SVG, ICO, BMP, TIFF), PDF, text, CSV, Word and Excel documents, video and audio are accepted; anything else is
|
|
86
|
+
refused with 400. The size limit is <code>uploads.maxFileSize</code> in <code>config/server.json</code>
|
|
87
|
+
(10 MB by default). One file answers with an object, several with an array.</p>
|
|
88
|
+
<pre class="code-block"><code>// Response 201 (one file)
|
|
89
|
+
{ "name": "photo.jpg", "url": "/media/photo.jpg" }
|
|
90
|
+
// Error 400
|
|
91
|
+
{ "error": "File type 'application/zip' is not allowed. Allowed types: images, documents, audio, video." }</code></pre>
|
|
92
|
+
|
|
93
|
+
<h3><span class="method-badge method-patch">PATCH</span><span class="endpoint-path">/api/media/:name</span></h3>
|
|
94
|
+
<p class="auth-note">Requires Bearer token + <code>media</code> update permission.</p>
|
|
95
|
+
<p>Rename a file. Pages that link to the old name are not changed. Answers 409 if the new name is taken.</p>
|
|
96
|
+
<pre class="code-block"><code>// Request body
|
|
97
|
+
{ "newName": "new-photo.jpg" }
|
|
98
|
+
// Response 200
|
|
99
|
+
{ "name": "new-photo.jpg", "url": "/media/new-photo.jpg" }</code></pre>
|
|
100
|
+
|
|
101
|
+
<h3><span class="method-badge method-delete">DELETE</span><span class="endpoint-path">/api/media/:name</span></h3>
|
|
102
|
+
<p class="auth-note">Requires Bearer token + <code>media</code> delete permission.</p>
|
|
103
|
+
<p>Delete a file.</p>
|
|
104
|
+
<pre class="code-block"><code>// Response 200
|
|
105
|
+
{ "success": true }
|
|
106
|
+
// Error 404
|
|
107
|
+
{ "error": "File not found" }</code></pre>
|
|
108
|
+
|
|
109
|
+
<h3><span class="method-badge method-get">GET</span><span class="endpoint-path">/api/media/:name/info</span></h3>
|
|
110
|
+
<p class="auth-note">Requires Bearer token + <code>media</code> read permission.</p>
|
|
111
|
+
<p>An image's size and format. Only for images that can be edited (JPEG, PNG, WebP, GIF, TIFF); others answer 400.</p>
|
|
112
|
+
<pre class="code-block"><code>// Response 200
|
|
113
|
+
{ "width": 1920, "height": 1080, "format": "jpeg" }</code></pre>
|
|
114
|
+
|
|
115
|
+
<h3><span class="method-badge method-post">POST</span><span class="endpoint-path">/api/media/:name/transform</span></h3>
|
|
116
|
+
<p class="auth-note">Requires Bearer token + <code>media</code> update permission.</p>
|
|
117
|
+
<p>Edit an image - the Media screen's image editor - and save it over the original or as a new file.</p>
|
|
118
|
+
<table class="table table-sm">
|
|
119
|
+
<thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead>
|
|
120
|
+
<tbody>
|
|
121
|
+
<tr><td><code>operations</code></td><td>object</td><td>Any of <code>rotate</code>, <code>flip</code>,
|
|
122
|
+
<code>flop</code>, <code>crop</code>, <code>resize</code>, <code>preset</code>, <code>adjustments</code>,
|
|
123
|
+
<code>watermark</code>, <code>border</code>, <code>format</code></td></tr>
|
|
124
|
+
<tr><td><code>saveAs</code></td><td>string</td><td>Optional. New file name; left out, the original is
|
|
125
|
+
overwritten</td></tr>
|
|
126
|
+
</tbody>
|
|
127
|
+
</table>
|
|
128
|
+
<pre class="code-block"><code>// Request body
|
|
151
129
|
{ "operations": { "resize": { "width": 800, "height": 600 }, "format": "webp" }, "saveAs": "hero-800.webp" }
|
|
152
|
-
|
|
153
130
|
// Response 200
|
|
154
|
-
{ "name": "hero-800.webp", "url": "/media/hero-800.webp",
|
|
131
|
+
{ "name": "hero-800.webp", "url": "/media/hero-800.webp", "width": 800, "height": 600 }</code></pre>
|
|
155
132
|
|
|
156
133
|
</div>
|
|
157
134
|
</div>
|
|
@@ -69,31 +69,75 @@
|
|
|
69
69
|
<div class="col-12">
|
|
70
70
|
<div class="docs-body">
|
|
71
71
|
|
|
72
|
-
<
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
72
|
+
<p>The site's navigation is made of <strong>menus</strong>: each is a file in <code>config/menus/<slug>.json</code>,
|
|
73
|
+
edited at Content > Menus, and shown by mapping it to a slot (the navbar, the footer) or placing it on a page
|
|
74
|
+
with <code>[menu slug="..." /]</code>. The endpoints need the <code>menus</code> permission for the action named.
|
|
75
|
+
The old single navigation file (<code>config/navigation.json</code>) was retired when menus arrived - see
|
|
76
|
+
Legacy navigation at the end.</p>
|
|
77
|
+
|
|
78
|
+
<h3><span class="method-badge method-get">GET</span><span class="endpoint-path">/api/menus</span></h3>
|
|
79
|
+
<p class="auth-note">Requires Bearer token + <code>menus</code> read permission.</p>
|
|
80
|
+
<p>Every menu you may see (a user confined to some projects sees their projects' menus), without items.</p>
|
|
81
|
+
|
|
82
|
+
<h3><span class="method-badge method-get">GET</span><span class="endpoint-path">/api/menus/:slug</span></h3>
|
|
83
|
+
<p class="auth-note">Requires Bearer token + <code>menus</code> read permission.</p>
|
|
84
|
+
<p>One menu, with its items. Sub-items go under <code>items</code>.</p>
|
|
85
|
+
<pre class="code-block"><code>// Response 200
|
|
86
|
+
{ "slug": "main", "name": "Main navigation", "variant": "dark", "position": "sticky",
|
|
78
87
|
"items": [
|
|
79
|
-
{ "
|
|
80
|
-
{ "
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
{ "
|
|
93
|
-
|
|
94
|
-
|
|
88
|
+
{ "text": "Home", "url": "/", "icon": "home" },
|
|
89
|
+
{ "text": "Services", "items": [ { "text": "Design", "url": "/design" } ] }
|
|
90
|
+
],
|
|
91
|
+
"meta": { "createdAt": "...", "updatedAt": "..." } }</code></pre>
|
|
92
|
+
|
|
93
|
+
<h3><span class="method-badge method-post">POST</span><span class="endpoint-path">/api/menus</span></h3>
|
|
94
|
+
<p class="auth-note">Requires Bearer token + <code>menus</code> create permission.</p>
|
|
95
|
+
<p>Create a menu. <code>slug</code> is required; <code>name</code>, <code>description</code>, <code>items</code> and
|
|
96
|
+
the display options (<code>variant</code>, <code>position</code>, <code>orientation</code>, <code>align</code>,
|
|
97
|
+
<code>side</code>, <code>float</code>, <code>highlight</code>, <code>binding</code>) are optional. An item may
|
|
98
|
+
carry <code>visibility</code> to show it only to some roles.</p>
|
|
99
|
+
<pre class="code-block"><code>// Response 201 - the created menu
|
|
100
|
+
// Error 409
|
|
101
|
+
{ "error": "Menu \"main\" already exists" }</code></pre>
|
|
102
|
+
|
|
103
|
+
<h3><span class="method-badge method-put">PUT</span><span class="endpoint-path">/api/menus/:slug</span></h3>
|
|
104
|
+
<p class="auth-note">Requires Bearer token + <code>menus</code> update permission.</p>
|
|
105
|
+
<p>Save a menu. The public pages that show it are refreshed.</p>
|
|
106
|
+
|
|
107
|
+
<h3><span class="method-badge method-delete">DELETE</span><span class="endpoint-path">/api/menus/:slug</span></h3>
|
|
108
|
+
<p class="auth-note">Requires Bearer token + <code>menus</code> delete permission.</p>
|
|
109
|
+
<p>Delete a menu. Refused while it is mapped to a slot.</p>
|
|
110
|
+
<pre class="code-block"><code>// Error 409
|
|
111
|
+
{ "error": "Cannot delete - menu is mapped to slot \"navbar\". Unmap it first." }</code></pre>
|
|
112
|
+
<p><code>POST /api/menus/:slug/duplicate</code> (create permission) makes a copy.</p>
|
|
113
|
+
|
|
114
|
+
<h3><span class="method-badge method-get">GET</span><span class="endpoint-path">/api/menu-locations</span></h3>
|
|
115
|
+
<p class="auth-note">Requires Bearer token + <code>menus</code> read permission.</p>
|
|
116
|
+
<p>Which menu fills each slot. <code>GET /api/menu-locations/registry</code> lists the slots there are
|
|
117
|
+
(<code>navbar</code>, <code>footer-primary</code>, <code>footer-legal</code>, <code>overlay</code>,
|
|
118
|
+
<code>admin-sidebar</code>, and any a plugin adds).</p>
|
|
119
|
+
<pre class="code-block"><code>// Response 200
|
|
120
|
+
{ "navbar": "main", "footer-primary": "footer", "admin-sidebar": "admin-sidebar" }</code></pre>
|
|
121
|
+
|
|
122
|
+
<h3><span class="method-badge method-put">PUT</span><span class="endpoint-path">/api/menu-locations</span></h3>
|
|
123
|
+
<p class="auth-note">Requires Bearer token + <code>menus</code> update permission.</p>
|
|
124
|
+
<p>Save the slot map (same shape as above).</p>
|
|
125
|
+
<pre class="code-block"><code>// Response 200
|
|
95
126
|
{ "success": true }</code></pre>
|
|
96
127
|
|
|
128
|
+
<h3><span class="method-badge method-get">GET</span><span class="endpoint-path">/api/context-menus</span></h3>
|
|
129
|
+
<p class="auth-note">Requires Bearer token + <code>context-menus</code> read permission.</p>
|
|
130
|
+
<p>Right-click menus for the public site (Content > Context Menus) are a separate kind of menu, with the same
|
|
131
|
+
shape of routes: <code>GET</code>, <code>POST /api/context-menus</code>, <code>GET</code>, <code>PUT</code>,
|
|
132
|
+
<code>DELETE /api/context-menus/:slug</code>, <code>POST /api/context-menus/:slug/duplicate</code>, and
|
|
133
|
+
<code>GET /api/context-menus/action-types</code> for what an item can do.</p>
|
|
134
|
+
|
|
135
|
+
<h3>Legacy navigation</h3>
|
|
136
|
+
<p><code>GET</code> and <code>PUT /api/navigation</code> (the <code>navigation</code> permission) still read and
|
|
137
|
+
write <code>config/navigation.json</code>, but the public site no longer reads that file: on first start after
|
|
138
|
+
menus arrived it was moved into the <code>main</code> menu and renamed <code>navigation.json.bak</code>. Use the
|
|
139
|
+
menus endpoints above.</p>
|
|
140
|
+
|
|
97
141
|
</div>
|
|
98
142
|
</div>
|
|
99
143
|
</div>
|
|
@@ -69,145 +69,125 @@
|
|
|
69
69
|
<div class="col-12">
|
|
70
70
|
<div class="docs-body">
|
|
71
71
|
|
|
72
|
-
<
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
</tr>
|
|
91
|
-
</tbody>
|
|
92
|
-
</table>
|
|
93
|
-
<pre class="code-block"><code>// Response 200
|
|
94
|
-
{ "html": "<p>Hello <strong>world</strong></p>" }</code></pre>
|
|
95
|
-
|
|
96
|
-
<h3><span class="method-badge method-get">GET</span><span class="endpoint-path">/api/pages/tags</span>
|
|
97
|
-
</h3>
|
|
98
|
-
<p class="auth-note">Requires Bearer token + <code>pages</code> permission.</p>
|
|
99
|
-
<p>Aggregate all unique tags across every page, sorted alphabetically.</p>
|
|
100
|
-
<pre class="code-block"><code>// Response 200
|
|
101
|
-
{ "tags": ["guide", "news", "tutorial"] }</code></pre>
|
|
102
|
-
|
|
103
|
-
<h3><span class="method-badge method-get">GET</span><span class="endpoint-path">/api/pages</span></h3>
|
|
104
|
-
<p class="auth-note">Requires Bearer token + <code>pages</code> permission.</p>
|
|
105
|
-
<p>List all pages with their metadata. Body content is excluded.</p>
|
|
106
|
-
<pre class="code-block"><code>// Response 200
|
|
107
|
-
[
|
|
108
|
-
{
|
|
109
|
-
"urlPath": "/about",
|
|
110
|
-
"title": "About Us",
|
|
111
|
-
"slug": "about",
|
|
112
|
-
"status": "published",
|
|
113
|
-
"layout": "default",
|
|
114
|
-
"tags": [],
|
|
115
|
-
"updatedAt": "2024-01-15T10:30:00.000Z",
|
|
116
|
-
"createdAt": "2024-01-01T09:00:00.000Z"
|
|
117
|
-
}
|
|
118
|
-
]</code></pre>
|
|
119
|
-
|
|
120
|
-
<h3><span class="method-badge method-get">GET</span><span class="endpoint-path">/api/pages/*</span>
|
|
121
|
-
</h3>
|
|
122
|
-
<p class="auth-note">Requires Bearer token + <code>pages</code> permission. The <code>*</code> is the
|
|
123
|
-
URL path,
|
|
124
|
-
e.g. <code>/api/pages/about</code>.</p>
|
|
125
|
-
<p>Retrieve a single page including its frontmatter and full body content.</p>
|
|
126
|
-
<pre class="code-block"><code>// Response 200
|
|
72
|
+
<p>Pages are Markdown files in <code>content/pages/</code>, addressed by their URL path. All endpoints need the
|
|
73
|
+
<code>pages</code> permission for the action named (read, create, update, delete). In the paths below,
|
|
74
|
+
<code>*</code> is the page's URL path without the leading slash, e.g. <code>/api/pages/about</code>.</p>
|
|
75
|
+
|
|
76
|
+
<h3><span class="method-badge method-get">GET</span><span class="endpoint-path">/api/pages</span></h3>
|
|
77
|
+
<p class="auth-note">Requires Bearer token + <code>pages</code> read permission.</p>
|
|
78
|
+
<p>List every page with its metadata (no body).</p>
|
|
79
|
+
<pre class="code-block"><code>// Response 200
|
|
80
|
+
[ { "urlPath": "/about", "title": "About Us", "slug": "about", "status": "published", "layout": "default",
|
|
81
|
+
"visibility": "public", "tags": [], "sortOrder": 0, "category": null, "project": null, "resolvedProject": "core",
|
|
82
|
+
"plugin": null, "bundled": false, "updatedAt": "2026-09-27T10:30:00.000Z", "createdAt": "...", "versionCount": 3 } ]</code></pre>
|
|
83
|
+
<p>A page may still carry a legacy <code>showInNav</code> value; nothing reads it - the site's navigation is edited in
|
|
84
|
+
Menus.</p>
|
|
85
|
+
|
|
86
|
+
<h3><span class="method-badge method-get">GET</span><span class="endpoint-path">/api/pages/*</span></h3>
|
|
87
|
+
<p class="auth-note">Requires Bearer token + <code>pages</code> read permission.</p>
|
|
88
|
+
<p>One page, with its frontmatter fields and full Markdown body.</p>
|
|
89
|
+
<pre class="code-block"><code>// Response 200
|
|
127
90
|
{ "urlPath": "/about", "title": "About Us", "body": "## Our Story\n\nWe started...", ... }
|
|
128
|
-
|
|
129
91
|
// Error 404
|
|
130
92
|
{ "error": "Page not found" }</code></pre>
|
|
131
93
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
</table>
|
|
162
|
-
<pre class="code-block"><code>// Response 201 - returns the created page object</code></pre>
|
|
163
|
-
|
|
164
|
-
<h3><span class="method-badge method-put">PUT</span><span class="endpoint-path">/api/pages/*</span>
|
|
165
|
-
</h3>
|
|
166
|
-
<p class="auth-note">Requires Bearer token + <code>pages</code> permission.</p>
|
|
167
|
-
<p>Update an existing page. Optionally rename it to a new URL path.</p>
|
|
168
|
-
<table class="table table-sm">
|
|
169
|
-
<thead>
|
|
170
|
-
<tr>
|
|
171
|
-
<th>Field</th>
|
|
172
|
-
<th>Type</th>
|
|
173
|
-
<th>Description</th>
|
|
174
|
-
</tr>
|
|
175
|
-
</thead>
|
|
176
|
-
<tbody>
|
|
177
|
-
<tr>
|
|
178
|
-
<td><code>frontmatter</code></td>
|
|
179
|
-
<td>object</td>
|
|
180
|
-
<td>Updated frontmatter fields</td>
|
|
181
|
-
</tr>
|
|
182
|
-
<tr>
|
|
183
|
-
<td><code>body</code></td>
|
|
184
|
-
<td>string</td>
|
|
185
|
-
<td>Updated Markdown content</td>
|
|
186
|
-
</tr>
|
|
187
|
-
<tr>
|
|
188
|
-
<td><code>newUrlPath</code></td>
|
|
189
|
-
<td>string</td>
|
|
190
|
-
<td>Optional. Rename the page to a different URL path</td>
|
|
191
|
-
</tr>
|
|
192
|
-
</tbody>
|
|
193
|
-
</table>
|
|
194
|
-
<pre class="code-block"><code>// Response 200 - returns the updated page object
|
|
195
|
-
|
|
94
|
+
<h3><span class="method-badge method-post">POST</span><span class="endpoint-path">/api/pages</span></h3>
|
|
95
|
+
<p class="auth-note">Requires Bearer token + <code>pages</code> create permission.</p>
|
|
96
|
+
<p>Create a page.</p>
|
|
97
|
+
<table class="table table-sm">
|
|
98
|
+
<thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead>
|
|
99
|
+
<tbody>
|
|
100
|
+
<tr><td><code>urlPath</code></td><td>string</td><td>Required. Public URL path, e.g. <code>/about</code></td></tr>
|
|
101
|
+
<tr><td><code>frontmatter</code></td><td>object</td><td>Frontmatter fields (title, status, visibility, layout,
|
|
102
|
+
...)</td></tr>
|
|
103
|
+
<tr><td><code>body</code></td><td>string</td><td>Markdown content</td></tr>
|
|
104
|
+
</tbody>
|
|
105
|
+
</table>
|
|
106
|
+
<pre class="code-block"><code>// Response 201 - the created page
|
|
107
|
+
// Error 409 - names the project the existing page belongs to
|
|
108
|
+
{ "error": "A page already exists at /about (project: core)", "urlPath": "/about", "project": "core" }</code></pre>
|
|
109
|
+
|
|
110
|
+
<h3><span class="method-badge method-put">PUT</span><span class="endpoint-path">/api/pages/*</span></h3>
|
|
111
|
+
<p class="auth-note">Requires Bearer token + <code>pages</code> update permission.</p>
|
|
112
|
+
<p>Update a page, and optionally move it to a new URL path. A move re-aims menu links that pointed at the old
|
|
113
|
+
path and drops the page's share links. Each save keeps a version (see Versions below).</p>
|
|
114
|
+
<table class="table table-sm">
|
|
115
|
+
<thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead>
|
|
116
|
+
<tbody>
|
|
117
|
+
<tr><td><code>frontmatter</code></td><td>object</td><td>Frontmatter fields</td></tr>
|
|
118
|
+
<tr><td><code>body</code></td><td>string</td><td>Markdown content</td></tr>
|
|
119
|
+
<tr><td><code>newUrlPath</code></td><td>string</td><td>Optional. Move the page to this path</td></tr>
|
|
120
|
+
</tbody>
|
|
121
|
+
</table>
|
|
122
|
+
<pre class="code-block"><code>// Response 200 - the updated page
|
|
196
123
|
// Error 404
|
|
197
124
|
{ "error": "Page not found" }
|
|
198
|
-
|
|
199
125
|
// Error 409
|
|
200
126
|
{ "error": "A page already exists at that path" }</code></pre>
|
|
201
127
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
{ "success": true }
|
|
128
|
+
<h3><span class="method-badge method-delete">DELETE</span><span class="endpoint-path">/api/pages/*</span></h3>
|
|
129
|
+
<p class="auth-note">Requires Bearer token + <code>pages</code> delete permission.</p>
|
|
130
|
+
<p>Delete a page and its share links.</p>
|
|
131
|
+
<pre class="code-block"><code>// Response 200
|
|
132
|
+
{ "success": true }</code></pre>
|
|
208
133
|
|
|
209
|
-
|
|
210
|
-
|
|
134
|
+
<h3><span class="method-badge method-get">GET</span><span class="endpoint-path">/api/pages/tags</span></h3>
|
|
135
|
+
<p class="auth-note">Requires Bearer token + <code>pages</code> read permission.</p>
|
|
136
|
+
<p>Every tag used on any page, sorted.</p>
|
|
137
|
+
<pre class="code-block"><code>// Response 200
|
|
138
|
+
{ "tags": ["guide", "news", "tutorial"] }</code></pre>
|
|
139
|
+
|
|
140
|
+
<h3><span class="method-badge method-post">POST</span><span class="endpoint-path">/api/pages/preview</span></h3>
|
|
141
|
+
<p class="auth-note">Requires Bearer token + <code>pages</code> read permission.</p>
|
|
142
|
+
<p>Render Markdown to HTML (shortcodes processed, no frontmatter), as the signed-in user sees it.</p>
|
|
143
|
+
<pre class="code-block"><code>// Request body
|
|
144
|
+
{ "markdown": "Hello **world**" }
|
|
145
|
+
// Response 200
|
|
146
|
+
{ "html": "<p>Hello <strong>world</strong></p>" }</code></pre>
|
|
147
|
+
|
|
148
|
+
<h3><span class="method-badge method-post">POST</span><span class="endpoint-path">/api/pages/preview/full</span></h3>
|
|
149
|
+
<p class="auth-note">Requires Bearer token + <code>pages</code> read permission.</p>
|
|
150
|
+
<p>Render unsaved editor content as the complete public page - layout, navbar, footer, theme and custom CSS - the
|
|
151
|
+
editor's Live Preview.</p>
|
|
152
|
+
<pre class="code-block"><code>// Request body
|
|
153
|
+
{ "urlPath": "/about", "frontmatter": { "title": "About" }, "body": "..." }
|
|
154
|
+
// Response 200
|
|
155
|
+
{ "html": "<!doctype html>..." }</code></pre>
|
|
156
|
+
|
|
157
|
+
<h3 style="margin-top:24px;font-size:15px;text-transform:uppercase;letter-spacing:.5px;opacity:.6">Share links</h3>
|
|
158
|
+
|
|
159
|
+
<h3><span class="method-badge method-post">POST</span><span class="endpoint-path">/api/pages/preview-links</span></h3>
|
|
160
|
+
<p class="auth-note">Requires Bearer token + <code>pages</code> update permission.</p>
|
|
161
|
+
<p>Make a share link that lets anyone with it see one page, draft or not, until it expires.
|
|
162
|
+
<code>expiresIn</code> is <code>1h</code>, <code>24h</code>, <code>7d</code> (default) or <code>30d</code>, or a
|
|
163
|
+
number of seconds up to 30 days. <code>GET /api/pages/preview-links?urlPath=/about</code> lists them and
|
|
164
|
+
<code>DELETE /api/pages/preview-links/:id</code> withdraws one.</p>
|
|
165
|
+
<pre class="code-block"><code>// Request body
|
|
166
|
+
{ "urlPath": "/about", "expiresIn": "7d", "label": "For the client" }
|
|
167
|
+
// Response 201
|
|
168
|
+
{ "id": "...", "urlPath": "/about", "expiresAt": "...", "token": "...", "url": "https://example.com/_preview?token=..." }</code></pre>
|
|
169
|
+
|
|
170
|
+
<h3 style="margin-top:24px;font-size:15px;text-transform:uppercase;letter-spacing:.5px;opacity:.6">Versions</h3>
|
|
171
|
+
|
|
172
|
+
<h3><span class="method-badge method-get">GET</span><span class="endpoint-path">/api/versions/list/*</span></h3>
|
|
173
|
+
<p class="auth-note">Requires Bearer token + <code>pages</code> read permission.</p>
|
|
174
|
+
<p>A page's saved versions (its History), newest first. The other version routes take a version's
|
|
175
|
+
<code>filename</code> from this list:</p>
|
|
176
|
+
<table class="table table-sm">
|
|
177
|
+
<thead><tr><th>Route</th><th>Permission</th><th>Does</th></tr></thead>
|
|
178
|
+
<tbody>
|
|
179
|
+
<tr><td><code>GET /api/versions/get/:filename/*</code></td><td>read</td><td>One version's content</td></tr>
|
|
180
|
+
<tr><td><code>POST /api/versions/create/*</code></td><td>update</td><td>Save a named version now
|
|
181
|
+
(<code>{"label": "..."}</code>)</td></tr>
|
|
182
|
+
<tr><td><code>POST /api/versions/restore/:filename/*</code></td><td>update</td><td>Put a version back as the
|
|
183
|
+
page</td></tr>
|
|
184
|
+
<tr><td><code>DELETE /api/versions/delete/:filename/*</code></td><td>delete</td><td>Delete one version</td></tr>
|
|
185
|
+
<tr><td><code>POST /api/versions/bulk-delete/*</code></td><td>delete</td><td>Delete several
|
|
186
|
+
(<code>{"filenames": [...]}</code>)</td></tr>
|
|
187
|
+
<tr><td><code>POST /api/versions/prune/*</code></td><td>delete</td><td>Keep only the most recent
|
|
188
|
+
(<code>{"keep": 10}</code>)</td></tr>
|
|
189
|
+
</tbody>
|
|
190
|
+
</table>
|
|
211
191
|
|
|
212
192
|
</div>
|
|
213
193
|
</div>
|