---
name: cedros-custom-page-authoring
description: Create, edit, preview, and publish Cedros pages and shared page templates through Page Builder or MCP; reuse linked layouts with per-page content.
---

# Cedros Custom Page Authoring

This guide covers a site-owned custom page assembled from the templates, zones,
blocks, media, and reusable components registered on one Cedros site.

## Scope the work

For a content edit, inspect the target page, its binding when present, and the
relevant live schema. Preserve unrelated layout, route, SEO, and publication
state. Read the shared-template section only for linked content or shared-design
work, and the custom-code section only when custom code is involved. A new page
needs the broader brief and layout workflow below; editing a draft does not
imply publication or a full-site redesign.

Reuse discovery and schemas from the same authenticated session while its
version and permissions remain unchanged. Refresh after reconnecting, a schema
error, or a site/extension change. Current revisions and stale-write checks still
apply to each mutation.

## Source-of-truth boundary

- This guide, the [Pages guide](/page-docs/pages.md), and the
  [Add / Edit Page guide](/page-docs/add-edit-page.md) are public and remain
  readable while the site is waitlisted, in maintenance, or otherwise gated.
- The [skill index](/skill.md) is the canonical entrypoint for the
  complete discovery landscape and current public authoring guides.
- The authenticated MCP registry is authoritative for the site's current
  templates, block catalog, schemas, permissions, write modes, content IDs, and
  publish blockers. Follow
  [Admin Site Operator](/skills/admin-site-operator.md), inspect
  `resources/list`, then read `cedros://admin/areas/content/pages`.
- Do not copy static tool schemas or guess block props. Read the catalog and
  exact tool schema from the current authenticated session before first use; refresh it when the session or contract changes.

## Choose the correct product

A normal custom page is site content, not an installable package. It has a
draft/review/publish lifecycle and is owned by the site. Use
[theme authoring](/skills/cedros-theme-authoring.md) to change presentation
across the site. Use
[extension authoring](/skills/cedros-extension-authoring.md) when the page
needs a new block type, server behavior, privileged data, or an
extension-owned route.

A source-level "custom page builder" task that edits React, React Native, or
Rust is repository work, not the portable Page Builder document described
here. Inspect that target repository's contracts and tests; do not invent a
cross-repository page package format.

## Standalone form pages

For an application, intake, or contact flow, use a saved Cedros form before
authoring a custom page. Forms already generate `/forms/{scope}/{formKey}`
with the site's theme, validated questions, shared submission handling, and a
confirmation screen. See [Forms](/page-docs/forms.md) and
[Form design](/page-docs/add-edit-form.md#design).

Discover `cedros.forms.definition.get` and `cedros.forms.definition.save`
through the authenticated registry. Read the existing definition and exact
schema. Its optional `presentation` object controls Split/Centered/Image
layout, background, width, density, progress, motion, and imagery. The admin
Design card edits that same object. Omit presentation on MCP save to keep the
existing design; send an empty object to reset it. Preserve unrelated fields.
The server retains extension provenance. Never hand-build submission IO or
replace validation to obtain a different appearance.

Use the editor's interactive preview to check questions and confirmation in
desktop/mobile and light/dark; preview answers are never submitted. Verify
reduced motion and long content. Saving an active form updates its public
page; keep drafts offline until publication is intended. These settings do
not change embedded `form-embed` blocks. For a form within a custom page,
discover that block's live props and let the containing page own its layout.

## Reviewed Cedros Forge starter handoff

An anonymous prospect starter exists only on a separately installed Cedros
Forge control plane. Ordinary Cedros client sites do not advertise or mount
that public capture service. A Forge bundle is evidence and proposed draft
input, not site content, a Page Builder document, or permission to republish.

Before using one:

1. require the Forge control plane's signed internal review approval for the
   exact bundle digest;
2. authenticate to the destination site and re-read its live Page Builder
   catalog and permissions;
3. choose individual `draftRequest` records and submit them through the normal
   authenticated content-create workflow with `contentType: "page"`; the
   content-create route produces the new draft;
4. review and replace text, marks, images, fonts, testimonials, privacy-sensitive
   material, and integrations whose rights or behavior are not confirmed; and
5. validate and preview the saved draft before considering the separate
   publish action.

Never treat the Forge submitter's attestation as destination-site authorization,
auto-import every candidate, or change a draft request to published status
during handoff.

## Page model

The stable concept is a versioned document selecting a template and placing
ordered blocks into the template's zones. Each block has a durable ID, a
registered type, and serializable props. The live catalog determines which
templates, zones, block types, patterns, starters, and props are valid on this
site.

## Shared layouts with per-page content

Before building or restyling a family of similar pages, inspect the site's shared
template library. Reuse a suitable published layout so future design changes reach
every linked page. Comparison, feature, extension, industry, tool, collection,
program, and legal pages are possible families, not templates guaranteed to exist
on every site. Discover their IDs and editable fields from the target site; do not
reuse another site's IDs or assume its library is installed. Keep genuinely unique
pages independent when a shared layout would not fit.

Distinguish three concepts:

- **Catalog template:** the registered zone contract selected by `document.template`
  (and the builder's `templateId` inputs).
- **Starter / Start from a design:** a one-time copy into an independent page.
- **Shared page template:** a site-owned layout plus typed content fields, linked
  through `attributes.sharedTemplate = {id, values}`. The page retains its own
  route, SEO, content values, and publication lifecycle.

A shared template UUID is not a catalog `templateId`. Bind it through
`cedros.page_builder.templates.bind`; copying its resolved document into each
page loses the shared relationship. The admin **Use template**, **Page content**,
and **Edit template** controls operate on the same system. See
[Shared page templates](/page-docs/add-edit-page.md#shared-page-templates)
for that UI workflow.

### Use a published template or edit linked content

1. Discover the exact `cedros.page_builder.templates.*` schemas and Pages tools in
   the authenticated registry. Call `cedros.page_builder.templates.list`, then
   inspect the chosen record's `published`, `publishedRevision`, `draft`,
   `revision`, and linked `pages`. Binding uses the published layout; an unpublished
   template must be reviewed and published before pages can use it.
2. Read the target page through `cedros.page_builder.document.get`, or create a
   page draft through the registered builder workflow. Preserve its route, SEO,
   and current content. Map that content to the published definition's field keys;
   defaults are starting points, not reviewed copy for the new page.
3. Call `cedros.page_builder.templates.bind` with `contentId`, the page's current
   `expectedRevisionId`, and `binding: {id, values}`. This saves a page draft only.
   For content edits, merge changes into the existing binding's complete `values`
   object before sending it: binding replaces the object, it is not a field patch.
   On a stale-revision error, re-read and reconcile rather than retrying blindly.
4. Re-read the saved page, validate it, refresh its preview, and check release
   readiness through the registered page tools. Review and publish the page
   separately. `cedros.page_builder.templates.preview` resolves the saved
   **template draft**, which may differ from the published layout used by the page;
   it is not a substitute for previewing the bound page.

For a one-page content change, use `templates.bind`, not `templates.save` or
`templates.publish`. To make a page independent, explicitly send `binding: null`
with its current revision; this preserves the resolved published design and values
as a page draft. Omitting `binding` is invalid. Detach only when independence is
intended, not as a workaround for a missing field or a layout edit.

### Create or revise the shared design

Use `cedros.page_builder.templates.save` with the full `definition` and the last
read template `revision` as `expectedRevision`. Creation uses a new UUID and
`expectedRevision: null`. A definition contains `name`, `description`, a version-1
authored `document`, and `fields`; inspect the live catalog for its blocks/zones
and the save schema for field contracts. Preserve existing block IDs and field
keys when changing the design. Saving creates a template draft, not a live change.

Build shared layouts from registered Page Builder components, not Raw Code.
The template must remain visually editable: separate hero, editorial sections,
capability tabs, comparison tables, resources, FAQs, and actions as appropriate.
Discover the live catalog before choosing components. `editorial-section`,
`resource-directory`, and `business-tool` are reusable components when advertised
by the target site's catalog. Read each component's `propsSchema` when provided:
it declares valid tool modes, resource item shapes, and media requirements. These
contracts are enforced when templates resolve for saving, binding, and publication.
If a needed interaction is absent, add a registered
component through the product or extension workflow, with editor controls,
validation, web/native rendering, and meaningful Markdown support; do not hide an
entire template in a page-sized custom-code block.

Expose only the content each page should own. Each field targets a block's props
through `blockId` and `path`, with a type, default, and optional requirement.
Use `list` fields and typed `itemFields` for repeated content such as FAQs and
resources. Bind the whole list property (for example `["items"]`); field paths
traverse objects, not array indexes. Keep layout options in the shared document
and content in page values. The Page content rail groups fields by component;
Edit template changes the shared component layout. Keep all representations meaningful. Required fields and type changes can
block existing pages. For additive list changes, typed defaults on new `itemFields`
fill only missing keys; they do not overwrite supplied values.

After saving, use `cedros.page_builder.templates.preview` with the returned
revision and representative `values` from linked pages, including long and sparse
content. Resolve validation issues and inspect the rendered layout. Before calling
`cedros.page_builder.templates.publish`, review the current linked `pages`, including
live and draft-only links, and confirm the intended scope is the shared design.
Publication validates both current and published linked content and changes every
linked live page's layout; it does not publish pending page content drafts or move
their published revision pointers. Verify affected public pages after publication.

`cedros.page_builder.templates.revisions` lists saved definitions.
`cedros.page_builder.templates.restore` copies a historical definition into a new
draft using the current `expectedRevision`; review and publish that draft separately
to restore a live design. Record template and page revisions separately.

## Theme integration for custom code

Registered blocks, patterns, and templates participate in the active theme
automatically. Prefer them when they can express the page. A raw-code block's
live React web output owns its markup and CSS, so it must consume the inherited
theme variables instead of introducing an independent palette or type system.

Use these semantic color variables inside React web custom code:

| Variable | Use |
| --- | --- |
| `--cedros-runtime-bg` | Page or section background |
| `--cedros-runtime-panel` | Raised surface or card fill |
| `--cedros-runtime-border` | Borders and separators |
| `--cedros-runtime-text` | Primary text |
| `--cedros-runtime-muted` | Secondary text |
| `--cedros-runtime-accent` | Links and strong accents |
| `--cedros-runtime-accent-soft` | Subtle accent or hover fill |
| `--cedros-runtime-action-bg` | Primary action background |
| `--cedros-runtime-action-fg` | Primary action text or icon |

Use `--cedros-font-body`, `--cedros-font-heading`, and
`--cedros-font-mono` for font families. Custom code can also follow the
theme's broader typography, spacing, shape, and elevation through
`--cedros-font-size-base`, `--cedros-line-height-body`,
`--cedros-line-height-heading`, `--cedros-space-section`,
`--cedros-space-content`, `--cedros-space-page-inset`,
`--cedros-radius-sm`, `--cedros-radius-md`, `--cedros-radius-lg`,
`--cedros-radius-pill`, `--cedros-shadow-sm`, `--cedros-shadow-md`, and
`--cedros-shadow-lg`.

### Page width and content measure

The theme owns the outer width of every custom page through
`routeSurfaces.authoredPage.containerWidth`, whose supported values are
`content`, `wide`, and `full`. Raw code should fill the width the host gives it;
it should not try to override that page frame. If the custom-page surface needs
a different outer width, change the theme's `authoredPage` surface rather than
adding escape rules to an individual page.

Use `width: 100%`, `max-width: 100%`, `min-width: 0`, and
`box-sizing: border-box` on the custom page root. Avoid `100vw`, fixed minimum
widths, large negative inline margins, and full-bleed backgrounds that escape
the host container. Those patterns ignore the theme's page inset and commonly
create horizontal overflow.

An individual page may narrow its own inner reading measure without changing
the outer frame. Use `--cedros-container-content` or
`--cedros-container-wide` with a fallback for that inner wrapper, for example
`max-width: var(--cedros-container-content, 48rem)`. A page cannot make itself
wider than the outer `authoredPage` surface.

Scope every rule under a page-specific root and provide a fallback for each
variable:

```css
.cedros-pricing-page {
  box-sizing: border-box;
  width: 100%;
  max-width: 100%;
  min-width: 0;
  color: var(--cedros-runtime-text, #111827);
  background: var(--cedros-runtime-bg, #ffffff);
  font-family: var(--cedros-font-body, system-ui, sans-serif);
}

.cedros-pricing-page__card {
  border: 1px solid var(--cedros-runtime-border, #e5e7eb);
  border-radius: var(--cedros-radius-lg, 1rem);
  background: var(--cedros-runtime-panel, #ffffff);
  box-shadow: var(--cedros-shadow-sm, 0 1px 2px rgb(0 0 0 / 5%));
}

.cedros-pricing-page__title {
  font-family: var(--cedros-font-heading, inherit);
}

.cedros-pricing-page__action {
  color: var(--cedros-runtime-action-fg, #ffffff);
  background: var(--cedros-runtime-action-bg, #111827);
}
```

Do not target host selectors such as `html`, `body`, or `.cedros-site` from
React custom code. Do not use `prefers-color-scheme`: the visitor can override
their operating-system preference, and the inherited variables already track
the resolved Cedros light/dark mode. If a non-token style truly needs a dark
variant, scope it under `.cedros-dark .cedros-pricing-page`.

A hard-coded color, font, radius, or shadow remains fixed when the site theme
changes. Use one only as a deliberate content-level design decision, then test
its contrast and fit against every supported theme and both visitor modes.

Plain HTML/CSS/JS mode renders in a sandboxed iframe and cannot inherit the
host page's theme variables. Use React web mode when custom content must follow
the active Cedros theme. These CSS variables are a web contract; React Native
custom code must use native primitives and be reviewed separately, while the
Markdown fallback is styled by its host renderer.

## End-to-end workflow

1. **Define the page brief.** Record audience, purpose, route, primary action,
   required sections, source-approved claims, media, accessibility needs, SEO
   intent, locale coverage, and the success signal.
2. **Read current state.** In the admin, open Pages and Page Builder. For an
   agent, load `cedros://admin/areas/content/pages`, then use the exact
   permission-filtered read tools returned by the registry to resolve an
   existing page or initialize a new draft.
3. **Resolve identity safely.** Use a unique lowercase route/slug, a human
   title, summary, and change note. Never overwrite a built-in,
   extension-owned, or existing route to resolve a collision.
4. **Choose reuse before layout work.** Inspect the shared template library and
   follow the binding workflow above when a published layout fits. Otherwise,
   inspect the live catalog and choose a supported zone template and optional
   starter. Check every target zone and block type before creating operations.
   Prefer registered blocks, patterns, and reusable components over raw custom code.
5. **Build in small draft revisions.** Add the page skeleton, then content,
   media, responsive layout, and metadata. Keep block IDs stable when editing.
   Re-read the saved document after meaningful changes and never publish an
   unsaved in-memory plan.
6. **Use least privilege.** Read, draft, and publish are distinct modes.
   Permissions and confirmation inputs come from the authenticated registry.
   If a required write or publish action is unavailable, stop and report the
   missing authority; do not route around it with generic storage tools.
7. **Validate the document.** Run the current Page Builder validation. Resolve
   unknown or incompatible blocks, invalid zones/props, missing required
   content, route conflicts, broken media, and localization issues. Preserve
   extension-owned and system-page constraints. Without a test site, and only when sending the artifact to that service is authorized, follow the
   live [centralized Forge authoring scan](https://cedros.ai/extensions/cedros-forge/skill.md)
   guide and use only a profile and endpoint it currently advertises. Treat the
   result as preliminary evidence.
8. **Test the rendered page.** Generate a fresh saved preview and inspect the
   actual site runtime at mobile and desktop widths. Verify keyboard and focus
   behavior, headings, landmarks, contrast, alt text, links, forms/actions,
   empty/error states, and no horizontal overflow. In a draft preview or test site, switch the preview theme and
   the visitor light/dark mode; do not change the production theme merely for testing. Then verify custom text, panels, borders, actions,
   and fonts change with their theme variables. Confirm the page fills but does
   not escape the active `authoredPage` container at each supported width.
9. **Review release readiness.** Check SEO title/description, canonical route,
   social image, media review, AI co-author review when used, translation
   status, analytics/CTA intent, and every live release blocker. Use the
   [Page Analytics guide](/page-docs/page-analytics.md) for post-publish
   measurement.
10. **Publish or schedule deliberately.** Publish only the reviewed saved
    revision, or schedule it for a future time through the current
    authenticated workflow. Re-open the public URL after release. Keep the
    prior revision available for rollback; unpublish rather than delete when
    reversibility matters.

## Packaging, compatibility, and security

- Ordinary custom pages are persisted site content. There is no standalone
  Cedros page ZIP to build or upload in this workflow.
- Compatibility is evaluated against the live template/block catalog and the
  installed extensions that own contributed blocks. Revalidate after changing
  a template, theme, locale set, or required extension.
- Do not place secrets, tokens, private customer data, unsafe scripts, or
  unreviewed third-party embeds in block props or metadata. Use host-managed
  media and provider seams.
- Treat preview links as scoped review credentials. Share them only with the
  intended reviewers and mint a new preview after the draft changes.
- Publishing a page does not prove search indexing, analytics ingestion, or a
  production rollout elsewhere. Verify those outcomes separately.

## Completion evidence

Record the content ID and route, reviewed revision, template and significant
block dependencies, validation result, preview URL/review, accessibility and
responsive checks, release-readiness result, publish or schedule result,
post-release smoke check, and rollback revision.
