Workspace
Content types and extensions
Build custom collections, bind fields and release reusable layouts through the administrator interface.
Content types describe structured collections
A content type defines the common shape and behavior of a collection. Posts and Pages are the default collections, protected from retirement and deletion. They share title, body, excerpt, visibility, media and publication behavior, while custom types can add scalar fields and permitted taxonomies. Upgraded installations retain legacy Events and Vehicles under Retired types, with entries and history preserved and website content withdrawn.
Administrators can create custom types in Content types, add supported scalar fields, save a definition draft and review its activation assessment. Activation makes that exact version available to forms, APIs and routes. Built-in definitions remain read-only. After activation, stored keys, field kinds and route capabilities are fixed; labels, help text, order, optional fields, appended choices and relaxed constraints can change compatibly.
| Type | Public path | Distinct behavior |
|---|---|---|
| Posts | /journal | Archive, search, categories and tags |
| Pages | Root and nested paths | Parent hierarchy; no ordinary type archive |
Sources: Installed type and taxonomy registry; TypeDefinition and supported scalar fields; Content type builder and catalogue.
Draft and activate a collection
Choose Create content type as an administrator. Set labels, the permanent type key and route base, supported taxonomies and public/archive/search behavior. Add fields, defaults and validation limits, then choose Save draft, Check impact, Activate saved version and Activate. The route base must be unique and avoid reserved application paths. Existing editors receive a conflict if a definition changes while they are editing; their values are retained for review.
{ key: "recipe", label: "Recipes", singular: "Recipe",
routeBase: "recipes", archive: true, hierarchical: false,
public: true, searchable: true,
fields: [
{ key: "preparation", label: "Preparation", type: "text", required: true },
{ key: "minutes", label: "Minutes", type: "number", required: true }
],
taxonomies: ["category", "tag"],
description: "Recipes with preparation notes and cooking time." }This example shows the definition shape used by the administrator services. The existing resource API, forms and public loader handle the activated collection. A source-code declaration alone does not register a custom type in an existing database. Relationships, repeaters, computed fields, new taxonomies and specialized indexed queries remain developer extensions.
Sources: Installed type and taxonomy registry; TypeDefinition and supported scalar fields; Content-type and component extension contract.
Retire, restore or permanently delete a collection
Retire type withdraws a collection and its entries from the website while keeping its entries, translations and history. Review the impact and resolve listed dependencies before confirming. Open Retired types and View retained content to inspect its read-only entries. Restore type enables editing again; it does not republish entries or reinstate cancelled publishing schedules. Review and publish entries separately.
Delete permanently removes the type's definitions and all its authored entries, translations, trash and revision content. Resolve current draft, published, scheduled and available reusable-component dependencies, check again and type the exact permanent key to confirm. Shared media, other types, historical snapshots belonging to other resources and audit/publication evidence are retained. The deleted key remains reserved. Posts and Pages are protected. These actions require an administrator session and are unavailable to API keys.
Historical references in other resources may remain after deletion. Their JSON stays unchanged. Deleted entry and type references show notices; original URL links may stop working. Choose Load for repair to copy a historical revision into an unsaved draft based on the current working revision. Autosave pauses, including after tab recovery. Remove or replace deleted references and choose Save changes; unresolved references cannot be saved or restored. Publishing is a separate step.
A changed impact assessment requires fresh review and confirmation. Retrying after a lost response reuses the same operation. Permanent deletion cannot remove copies already stored in earlier exports or backups.
Sources: Content type builder and catalogue; Content type retirement and permanent deletion; Archive route registration.
Validation and presentation are separate decisions
Supported fields include text, number, boolean, calendar date, datetime, select, rich text, typed links, media, single or ordered multiple relationships, and bounded scalar lists. A select declares its allowed options. Relationships target one declared kind/type in the entry language. Lists and multiple relationships allow at most 100 items; models allow at most 50 fields. Posts and Pages accept compatible optional custom fields. Required fields may remain empty in a saved draft but must be valid before publication; unknown field keys are rejected. Date-time values represent instants with an offset, with the interface helping the editor choose a local time. Cross-field rules, such as an event ending after it starts, belong in server validation rather than only in form controls.
Add Content field to a visual composition and choose a type, field and compatible text, number, currency, date or yes/no format. Bindings read the current entry, using its language and the site timezone. Required missing values block publication; optional fields can use a fallback. Use current-entry bindings in content or single:TYPE templates (page for pages). Unscoped shared sections and archive/index templates cannot use them in this release. Numeric fields do not automatically add range filters or specialized sorting.
Sources: TypeDefinition and supported scalar fields; Field, composition and reference validation; Component rendering and fields; Content-type and component extension contract.
Treat stored contracts as long-lived data
Each content revision pins its exact definition version. Restoring history preserves that pin and does not rewrite the original snapshot. Component instances similarly pin immutable releases. Administrators build Components from supported blocks, expose typed inputs and publish a release. Inserting materializes defaults. Releasing v2 leaves v1 instances unchanged; a reviewed upgrade changes only a consuming draft, with undo and a separate publication decision. Image inputs use literal media selections because scalar fields are not typed image references.
For relational changes, update the Drizzle schema, generate SQL, review it and verify a fresh database plus an upgrade copy. Preserve custom migration constraints and runtime grants. For components that contain media or resource identifiers, extend reference extraction and authorized rendering as well as the visible editor. Otherwise publication, deletion protection and public media access cannot reliably understand the relationship. Run draft/save/publish/reload, invalid-input, role and public-rendering cases before considering the extension complete.
npm run db:generate
npm run typecheck
npm run test:integration
node scripts/verify-extension.mjsArchive hides a component from new insertion without changing pinned instances. Unpublishing or trashing a component with public consumers is rejected, and released revisions and media remain retained. The historical extension exercise predates the database registry; use the current content-builders integration suite for activation and release-pin behavior. Generate migrations only for relational changes and retain the exact version evidence in backups and restores.
Sources: Relational schema; Field, composition and reference validation; Content-type and component extension contract; Executed generic extension exercise; Drizzle schema declarations.