Components and pages
A component is a JSON Schema stored as an ordinary document, a page is a document bound to a component marked as a page, and the dashboard's built-in preview draws either one from the roles its fields declare.
Why each shape is described once
Structured content needs a shape. Without one, a hero can lose its headline and nobody notices until the page is live. Quillet describes each shape once, as a component, and puts that one description to work everywhere a shape matters. It refuses a save that does not fit. It draws the form a content manager fills in. And it generates the TypeScript types an engineer's site compiles against.
The description is written in JSON Schema, draft 2020-12. Because one definition feeds the validator, the form and the type generator, the three cannot drift apart. A component is also stored as a document under _schemas/, so the same machinery that versions, publishes, compares and pushes every other document does the same for components. Nobody has to write the JSON by hand: the component builder writes it, and its JSON tab shows the result.
How a component shapes documents and pages
Components
You bind a document to a component by naming the component on the document, or by putting the document in a folder whose _index names one. Quillet checks a bound document on every save against the component's current draft, and on every publish against the component's published version. When a check fails, the error is reported per field, at the path that caused it.
Inline or by reference
A component can sit inside another document in two ways, and the one you pick decides who an edit affects.
- A block is a copy, inline in the page's body and marked with
_component. Editing it changes this page and no other. - A reference is a pointer,
{ "$ref": "<key>" }, to a document of its own. Delivery replaces the pointer with that document's published body. When you publish the referenced document, every page that points at it changes, and none of those pages is published again.
Use a block for content that belongs to one page. Use a reference for content you want to change in one place, such as a shared banner. While anything still points at a referenced document, that document cannot be deleted or renamed.
Pages
A page is not a separate kind of record. It is a document bound to a component whose root carries x-quillet.page: true, usually along with an SEO group and a block list. The design considered a separate page store and rejected it, because that store would have needed its own versions, publishing, fallback, references and promotion: a second copy of everything a document already does. The design also states what this choice costs. A page component can be written with no SEO group and no blocks, and nothing refuses it. The builder shows a notice instead.
Roles, and why the preview reads them
A role says what a field is for: heading, eyebrow, body, media, action, meta, hidden or seo. A role constrains no data and adds nothing to the types. What reads the roles is Content preview, which uses them to draw a document in the dashboard with no site involved. A field with no role gets one by a rule short enough to say aloud: the first short plain text field is the heading, a link is a button, an image is media. The alternative, choosing a layout for each component, was rejected. It would be a second modelling job, and a wrong mapping would fail silently.
How to
Dashboard
- Open the Components tab, press New and choose Component. Name it
ctaand press Save. - Press Add field: name
label, type Text, tick Required. Add a second field,link, of type Link. - Press Save, then Publish.
- Open a page whose block list allows CTA, press Add block and choose CTA. The block is a copy that lives inside this page.
API
Read a page that references a component:
curl -s -u '<keyId>:<secret>' \
'http://localhost:3000/d/v1/<project>/<env>/content/<key>'Each block in the answer carries _component. Each reference is replaced by the target's body, and _meta.refs lists every reference that was reached, with the target's version.
Limits
- The dialog that inserts a component does not yet explain how a copy differs from a reference.
- Changing a component does not re-check the documents already saved under it. The component's Instances tab reports which ones still match; there is no workflow that repairs the rest.
- Components embed one another at most five levels deep, and a component may not contain itself.
- Delivery follows references three levels deep by default and five at most, and it inlines at most 200 references in one answer.
- If a block list grows from one allowed component to two, every stored block without
_componentbecomes unsavable until it names its component. - The form view does not cover every schema. Arrays of objects, for one, are edited as JSON.
Related
- Components and the builder: every field type and setting.
- Inline and referenced components: choosing, and what follows.
- Pages: roles, SEO fields and block lists.
- Pages and preview: editing a page and previewing it.
- Generated types: the TypeScript a component becomes.