The CWA is in heavy development
The CWA is still in alpha and not ready for production - some code and implementations are likely to change. If you would like to try out the CWA, please enjoy what we have provided and feel free to provide feedback, or get involved on GitHub.
DraftCore Concepts

The Data Model

The six resource types that form the content graph behind every CWA page — and how they chain together.

Every page in a CWA site is described by a chain of resources stored in the API. Understanding this chain is the single most useful thing you can do before writing any code.

The Resource Chain

The diagram below shows both paths through the chain — static pages (Route → Page directly) and dynamic pages (Route → PageData → Page template):

Keyblue: UI resources with a uiComponent field (you write a Vue template). Violet: resources you define in PHP by extending a CWA abstract. Stone: core structural resources managed by CWA (no code required). Component types are blue but also require a PHP class like PageData.

Route

Maps a URL path to either a Page (for static pages) or a PageData record (for dynamic pages). Also handles redirects.

Page

The content structure rendered inside a Layout. Its uiComponent field maps to your Vue template file.

  • Static page: one page, one URL, fixed content regions
  • Template page (isTemplate: true): reused across many PageData records — one per article, product, event, etc.

PageData

Used for dynamic sections (blogs, events, products). Instead of a Route pointing directly to a Page, it points to a PageData record. That record carries a page field naming the Page template to render, plus the URL's own content fields.

  • Extends AbstractPageData, which provides title and metaDescription for SEO
  • Your custom fields (headline, body, image) live here
  • Its own Route gives it a live URL (e.g. /blog/my-first-post)

Layout

The outer shell of every page — header, footer, navigation. Every Page has exactly one Layout.

  • uiComponent: "CwaLayoutPrimary" → renders your app/cwa/layouts/primary.vue
  • Has its own ComponentGroups (e.g. a nav region)

ComponentGroup

A named region within a Layout or Page — the area where admins add and reorder content.

  • The reference string (e.g. "hero", "nav") is what you use in your Vue template: <CwaComponentGroup reference="hero" :location="iri" />
  • Can restrict which component types are allowed via allowedComponents

ComponentPosition

A single ordered slot inside a ComponentGroup. Holds exactly one Component, or a binding to a PageData field.

Component

Your custom content items: titles, paragraphs, images, hero sections, navigation links, etc.

  • uiComponent: "Title" → renders app/cwa/components/Title/Title.vue
  • Can be publishable (draft → published workflow)

A Concrete Example

For a blog, a Route points to a BlogArticle PageData record rather than a Page directly. BlogArticle carries a page field naming BlogTemplate as the Page to render. BlogTemplate has a ComponentGroup containing a ComponentPosition with pageDataProperty: "htmlContent" — at render time that position resolves to whatever HtmlContent component is stored on the current BlogArticle. The dashed line in the diagram shows that runtime binding:

_metadata

Every resource the API returns includes a _metadata envelope:

{
  "@id": "/component/titles/abc-123",
  "@type": "Title",
  "title": "Hello World",
  "_metadata": {
    "persisted": true,
    "publishable": { "published": true, "publishedAt": "2024-01-01T00:00:00Z" },
    "mediaObjects": {}
  }
}

Your Vue component reads resource?.data?.title. The _metadata is used by the module internally.