The Data Model
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):
Key — blue: 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 providestitleandmetaDescriptionfor 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 yourapp/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
referencestring (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"→ rendersapp/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.