Skip to main content
The schema says which pages exist and which sections each has. The database holds the content. A page renders from the schema before any content exists. The first edit creates its row. Goal: /careers/, a hero and a list of open roles editors can add to. A draft until it is ready.

1. Declare the page

src/lib/admin-schema.ts:
hero already exists in the template. role-list does not, so:

2. Build the component

src/components/careers/RoleList.astro:

3. Register it

src/lib/components.ts:

4. Make roles addable

src/lib/admin-schema.ts, under components:
The href has no anchor on the page, so it is set in this form and edited from the item’s cog.

5. Run dev

pnpm dev, open /careers/. The page renders from the schema. No row exists yet.

6. Edit

Open /admin, go to Careers, press Edit. The bar reads “Draft page”. Press the tab on the roles list, Add role, fill the form. Click the hero title and change it. Publish. That first Publish creates the row:
hero and roles are the schema keys. The role’s id was generated when it was added.

7. Ship

Remove draft: true, merge. The next production build includes /careers/.

8. Add a section later

One line under sections:
icon-grid already exists, so nothing else to build. It renders on the next dev start. The row is untouched until someone edits the new section. Remove a line and the section stops rendering. Its content stays in the row.

The keys

Slugs may nest: "help/faq". Keys ending in * are palettes for a family of pages, not pages.

More examples

A fixed page with three sections and nothing addable:
A page editors compose. One fixed hero, then whatever they add:
A family of pages with a shared palette:

Ids

The section key is the component id. The page template passes it to the renderer, the renderer puts it on its wrapper, and the editor saves under it. You never type an id anywhere else.
Sections editors add get generated ids with a c_ prefix. Another page can point at a section by name:

A page that already exists

Its sections have generated ids. Declare it by title only, or declare only the sections you are adding:
Declaring an existing section under a new key adds an empty copy beside it.

Drafts

Public routes read getSitePages() from lib/pages.ts. The preview route reads getPreviewPages(). Both come with the template. admin, preview and api cannot be pages.

Next steps

Add a component

A renderer, then one line in sections.

Page schemas

Everything the schema can declare.