CMS Overview
How Yayaw content surfaces, data models, media, sections, pages, design tokens, and email templates fit together.
Overview
Yayaw's CMS is the content operating layer inside the dashboard. It combines structured data, reusable sections, pages, media assets, public design tokens, transactional email templates, and component recipes under one authorization model.
The main entry point is:
/dashboard/content
That dashboard summarizes page inventory, section inventory, media storage, published CMS data, AI jobs, publication health, and shortcuts to every content surface available to the current user.
Surface Map
| Surface | Route | Purpose |
|---|---|---|
| CMS dashboard | /dashboard/content | Operational overview and content health |
| Pages | /dashboard/content/pages | Public and organization page composition |
| Sections | /dashboard/content/sections | Reusable page sections and generated recipes |
| Data models | /dashboard/content/data-models | Typed CMS model definitions |
| Data entries | /dashboard/content/data | Published singleton and collection content |
| Media | /dashboard/content/media | Organization-scoped binary assets and generated images |
| Components | /dashboard/content/components | UI component registry, previews, and imports |
| Design tokens | /dashboard/content/design-tokens | Runtime public-theme token overrides |
| Email templates | /dashboard/content/email-templates | React Email transactional templates |
Content Stack
The CMS is layered deliberately:
- Data models define typed fields, localization rules, and cardinality.
- Data entries publish shared values such as header menus, footer menus, and site variables.
- Media assets provide durable public URLs for selected or generated files.
- Components define the reusable UI inventory and recipe renderers.
- Sections define reusable page units with neutral example content and editable inputs.
- Pages compose layout nodes, component references, and published section references into public or organization-member routes, then fill section inputs through page-level bindings.
- Design tokens affect the public runtime presentation without changing page documents.
- Transactional email templates reuse CMS variables where appropriate but send through the email runtime, not the public page renderer.
This split keeps reusable structure in one place while page-specific editorial
copy stays on the page instance. Section templates should behave like a catalog
or Storybook example: use neutral fixture copy such as Lorem Ipsum in the
section itself, then bind final copy, links, JSON lists, and media through
PageSection.inputBindings or PageSection.mediaBindings when the section is
placed on a page.
Authoring Flow
A typical CMS change follows this path:
- Create or update the structured source in data models, data entries, or media.
- Build a reusable section when the content should appear on more than one page.
- Compose the page in the Puck editor using built-in layout nodes, section references, and direct component references only when needed.
- Publish the page or section after validation diagnostics are clean.
- Verify the public or organization-member runtime route.
AI-assisted flows follow the same persistence model. Page AI promotes generated content into reusable sections, Page AI image generation persists media through the media library, and missing section publication causes an explicit failure instead of an inline fallback.
MCP-assisted page design follows the same product model. A simple design prompt
should first inventory components, sections, media, and design tokens, then
create draft reusable composition sections, assemble a draft page from
PageSection references, and return validation diagnostics. Publishing remains
an explicit follow-up step for both sections and pages.
Runtime Resolution
Published content resolves from immutable revisions and publication rows:
- pages load
ui_page_publicationsand render the publishedPuckPageDocumentV1 - section references resolve through
ui_section_publications, first by current section ID and then by scoped slug/slug fallback so older page revisions keep rendering after section IDs are repaired - page-level
PageSectionbindings override section fixture props at runtime, so a catalog section can stay generic while each page instance carries the final localized content - data bindings resolve published global or organization CMS data entries
- media bindings use the stored public URL from
media_assets - public design tokens resolve from saved semantic token payloads
- transactional emails load the active database template for the requested locale before falling back to component defaults
Global public pages feed /sitemap.xml and public SEO metadata. Organization
member pages require membership and emit noindex metadata even when page-level
SEO fields exist.
Localization
CMS documents use the configured app locales from src/config/i18n.config.ts.
Current locales are English and French.
Localized content appears in:
- page copy and SEO fields
- global and organization data entry values
- header and footer menu entries
- generated section recipe values, including the legal-page
legalvariant - transactional email subjects, preview text, body HTML, and text exports
Generated page section bindings are stored as JSON object text in the Puck
document (propsBindingsJson, apiBindingsJson, harnessBindingsJson, and
related binding fields). Validation blocks malformed binding JSON and generated
sections without a valid variant binding so MCP or dashboard saves cannot
silently publish runtime fallback sections.
The English docs are canonical. French content may exist in the product, but new technical documentation should update English first.
Authorization
The CMS uses Yayaw's group and role authorization model. Dashboard navigation is only a hint; server loaders, actions, services, and MCP operations must still authorize every read or mutation.
Common CMS resources:
pagesectionsglobal-datamediacomponentsglobal-variablesemail-template
Organization members normally receive list/read access for organization-scoped content. Managers, admins, owners, and superadmins receive manage access according to their group role bindings.
Control Plane
Operational CMS workflows should share service logic across the dashboard, MCP, CLI scripts, and tests when they are exposed outside the UI.
Current control-plane coverage includes:
- page operations
- component catalog operations
- reusable section operations
- draft CMS page design orchestration
- CMS data operations
- media generation operations
- design token operations
- transactional email template operations
- billing catalog operations used by CMS variables
When adding a CMS feature, decide whether trusted MCP clients should operate it.
If yes, add typed schemas, a reason for writes, audit records, authorization
checks, and documentation updates. If no, document why the feature is
intentionally dashboard-only.
Operational Rules
- Store reusable content as published data, media, sections, or templates.
- Keep page documents as composition documents, not duplicated content stores.
- Do not execute DB-stored component source code.
- Do not store media binaries in Postgres.
- Keep public design tokens scoped outside dashboard and auth routes.
- Keep global CMS data and organization CMS data scoped explicitly.
- Revalidate affected dashboard and public runtime paths after publish/archive.
- Treat generated assistant files as derived artifacts; update
content/llm/llm-source.mdfirst and regenerate them.
Validation
Useful checks after CMS documentation or CMS behavior changes:
bun run docs:generate
bun run docs:check-links
bun run docs:check-translations
bun run docs:llm:generate
bun run docs:llm:check
bun run check
bunx tsc --noEmitRun domain tests as needed when implementation changes touch pages, sections, data models, media, components, tokens, or email templates.