You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/features/content-storage.md
+4-6Lines changed: 4 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -166,7 +166,6 @@ This is the single source of truth for slug derivation used by all admin write p
166
166
|`server/repositories/data/rows/mapper.ts`| Internal: hydrated SELECT builder + `DataRowRow → DataRow` mapper (not part of the public barrel) |
167
167
|`server/repositories/data/rows/index.ts`| Barrel for the `rows/` directory |
168
168
|`server/repositories/data/publish.ts`| Publish persistence (`persistDataRowPublish` writes `data_row_versions`) + public-route lookups; the orchestration (lock, artefacts, cache bump) is `server/publish/publishRow.ts`|
169
-
|`server/publish/templateSeeding.ts`| Seed default entry template for new postType tables (publish layer — it publishes a page row) |
170
169
|`server/repositories/data/shared.ts`| Shared helpers: `userRefAt` (typed accessor per prefix — unknown prefix is a compile error), `userRefColumns` / `userRefJoin` (SQL fragment builders — the single source for the four `<prefix>_*` user-ref join columns and LEFT JOIN clauses, spliced verbatim by both `rows/mapper.ts` and `publish.ts`), `UserJoinColumns` (interface for all four `<prefix>_*` column groups — always present via LEFT JOIN, `null` when no user matched) |
171
170
|`server/repositories/data/index.ts`| Barrel for the whole `data/` directory |
172
171
@@ -228,9 +227,7 @@ For postType rows, `publishDataRow` does the same but incrementally: writes the
228
227
229
228
See [docs/features/publisher.md](publisher.md) for the full pipeline.
230
229
231
-
For **post-types**, each `data_table` has a **default entry template** (a `pages` row with `template.target = { kind: 'postTypes', tableSlugs: [table.slug] }`). When you publish a post, the renderer resolves the template chain for the entry route (`resolveTemplateChain`) and renders the merged tree with the post row pushed onto the entry stack as `currentEntry`. Dynamic bindings on the template nodes resolve `currentEntry.title`, `currentEntry.body`, etc.
232
-
233
-
The entry template is seeded automatically when a new postType `data_table` is created (`backfillDefaultEntryTemplates(db)` at boot for tables that predate the template system). See [docs/features/templates.md](templates.md) for the full template model.
230
+
For **post-types**, public row routes require an explicitly authored entry template (a `pages` row with `template.target = { kind: 'postTypes', tableSlugs: [table.slug] }`). When you publish a post, the renderer resolves the template chain for the entry route (`resolveTemplateChain`) and renders the merged tree with the post row pushed onto the entry stack as `currentEntry`. Dynamic bindings on the template nodes resolve `currentEntry.title`, `currentEntry.body`, etc. Without a matching entry template, the published row exists in the CMS but its public detail URL returns 404. See [docs/features/templates.md](templates.md) for the full template model.
234
231
235
232
### Scheduled publishing
236
233
@@ -252,9 +249,10 @@ The field appears in the postType's edit form and is queryable from loops.
252
249
253
250
1. Open the Data workspace.
254
251
2. Create a new `data_table` with `kind: 'postType'`.
255
-
3. The system seeds the built-in fields (`title`, `slug`, `body`, `featuredMedia`, `seoTitle`, `seoDescription`) and a default entry template.
252
+
3. The system seeds the built-in fields (`title`, `slug`, `body`, `featuredMedia`, `seoTitle`, `seoDescription`).
256
253
4. Add custom fields as needed.
257
254
5. Add posts via the Content workspace.
255
+
6. Create a post-type template in the Site workspace if the collection needs public detail pages.
258
256
259
257
### Create a "data" table (no workflow)
260
258
@@ -351,7 +349,7 @@ Events are emitted from `server/publish/contentEvents.ts`, which also exports `a
351
349
- `server/repositories/data/` — `tables.ts`, `rows/` (split by responsibility), `publish.ts`, `shared.ts`
352
350
- `server/handlers/cms/data/` — generic data endpoints
353
351
- `server/handlers/cms/pages.ts`, `components.ts`, `layouts.ts` — typed endpoints for the system tables
@@ -318,14 +317,14 @@ Store action: `convertTemplateToPage(pageId)` in `siteSlice`.
318
317
319
318
---
320
319
321
-
## Seeding — default entry templates
320
+
## Entry templates are explicit
322
321
323
-
When a postType `data_table`is created, `ensureDefaultEntryTemplate(db, table)` in `server/publish/templateSeeding.ts` inserts a default template page (idempotent — it no-ops if one already targets the table):
322
+
Creating a postType `data_table`does not create a page. Entry templates are ordinary pages that users create, convert, and delete through the Site workspace. A published row detail URL (`/<route-base>/<row-slug>`) renders only when a matching template exists:
- Page tree: `base.body` > `base.text` (`<h1>` bound to `currentEntry.title` via token interpolation) + `base.outlet`(bound to `currentEntry.body` via `html` format)
325
+
- Page tree: any authored layout with a `base.outlet`where the row body should flow
327
326
328
-
`backfillDefaultEntryTemplates(db)` at boot covers postType tables created before the template system was added.
327
+
Without a matching entry template, the row remains publishable CMS content but its public detail URL returns 404.
329
328
330
329
---
331
330
@@ -340,12 +339,11 @@ When a postType `data_table` is created, `ensureDefaultEntryTemplate(db, table)`
340
339
341
340
### Add an entry template for a postType
342
341
343
-
When a postType is created, the system seeds a default entry template automatically. To customize:
344
-
345
-
1. Open the template page in the visual editor.
346
-
2. Edit it like any page — bind nodes to `currentEntry.<field>` via the Properties panel.
347
-
3. Add `base.outlet` anywhere you want the post body to flow.
348
-
4. Publish.
342
+
1. Create a new page or choose an existing page in the visual editor.
343
+
2. Open Template settings and choose **Post types**.
344
+
3. Select the target collection slug(s).
345
+
4. Build the layout — bind nodes to `currentEntry.<field>` via the Properties panel, and add `base.outlet` where the post body should flow.
346
+
5. Publish.
349
347
350
348
### Share a layout across post types
351
349
@@ -384,7 +382,7 @@ node.props.text = 'Posted by {currentEntry.author.displayName} on {currentEntry.
384
382
|---------|------------|
385
383
| Reading `currentEntry` from a module's `render` without bindings | Set `dynamicBindings` on the node — keeps the schema honest |
386
384
| Hardcoding a template's slug in server handlers | Use `resolveTemplateChain(site, ctx)`|
387
-
| Creating a template page via raw `INSERT INTO pages`| Use `ensureDefaultEntryTemplate(...)` or the admin dialog |
385
+
| Creating a template page via raw `INSERT INTO pages`| Use the Site workspace template dialog |
388
386
| Walking a deep binding path with `JSON.parse(JSON.stringify(...))`| Use `walkFieldPath(frame, 'a.b.c')`|
389
387
| Expecting to visit a template page at its own slug | Template pages are never directly routable — the live router and bake loop both skip them |
390
388
| Inlining `page.template?.target.kind === 'everywhere' ? … : …` in UI code | Use `templateTargetLabel(page)` from `@core/templates`|
@@ -411,7 +409,6 @@ node.props.text = 'Posted by {currentEntry.author.displayName} on {currentEntry.
411
409
-`src/admin/pages/site/hooks/useTemplatePreviewContext.ts` — synthetic preview context for the canvas
412
410
-`src/admin/pages/site/hooks/useActiveLivePath.ts` — resolves the toolbar "Open live page" path for templates
Copy file name to clipboardExpand all lines: docs/server.md
-2Lines changed: 0 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -35,7 +35,6 @@ server/index.ts
35
35
│ (selects migrations-pg.ts OR migrations-sqlite.ts based on dialect)
36
36
│
37
37
├─→ syncSystemRoles(db) ← force-resets Owner capabilities every boot
38
-
├─→ backfillDefaultEntryTemplates(db) ← ensures every postType table has a default entry tpl
39
38
├─→ mediaStorageRegistry.configureLocalDisk({ uploadsDir }) ← register local-disk media adapter
40
39
├─→ activateInstalledServerPlugins(db, uploadsDir) ← run plugin lifecycle: activate
41
40
│
@@ -511,7 +510,6 @@ Server-side publishing helpers live in `server/publish/`:
511
510
| `holeRuntime.ts` | Layer C client-side runtime (~668 B). Exports `runInstaticHoleRuntime` (TS source) and `HOLE_RUNTIME_JS` (IIFE-serialized for browser delivery). |
512
511
| `publishSite.ts` | Full-site publish orchestrator (`publishDraftSite`): phase-1 builds, the short `persistSitePublish` transaction, Layer A bake + slot swap, Layer B bump. |
513
512
| `publishRow.ts` | Per-row publish orchestrator (`publishDataRow`) + `removeDataRowArtefact`: persist via the data repository, in-place artefact update, Layer B bump. |
514
-
| `templateSeeding.ts` | Default entry-template seeding for postType tables (creates + publishes a page row; called by table-creation entry points, boot, and post-import backfill). |
| `publishedHtmlPipeline.ts` | Plugin frontend-asset injection + `publish.html` filter chain. Runs at publish time for every baked page (complete doc or hole shell); also runs in the Layer B factory for query-string / live renders (cached). |
0 commit comments