Appearance
Pages Configuration
The .dcs/pages.yaml file defines which pages of a site are managed through the DCS portal. It drives the page snapshot system and sets each page's type and protection rules.
Overview
yaml
# .dcs/pages.yaml
version: 3
siteSlug: my-site
generatedBy: dcs-portal
pages:
- slug: home
path: /
type: static
title: Home
deletable: falseModern (v3) configs do not list text keys per page — editable text keys are discovered automatically during snapshot capture, and the editable values live in .dcs/content.yaml. See Text Keys below.
Schema
Root Properties
| Property | Type | Required | Description |
|---|---|---|---|
version | number | Yes | Schema version (current default: 3) |
siteSlug | string | — | Site slug this config belongs to |
lastUpdated | string (RFC 3339) | — | When the config was last generated |
generatedBy | string | — | Who/what generated it (e.g. dcs-portal) |
pages | array | Yes | List of page definitions |
globalTextKeys | array | — | Text keys shared across all pages (nav, footer, …) |
excluded | array | — | Glob patterns for paths never managed (e.g. /blogs/**) |
snapshot | object | — | Snapshot capture settings (see below) |
Page Properties
| Property | Type | Required | Description |
|---|---|---|---|
slug | string | Yes | Unique, URL-safe identifier |
path | string | Yes | URL path for the page (dynamic paths use :param) |
type | string | Yes | One of static, index, dynamic, blog, event, form |
title | string | Yes | Human-readable page title |
deletable | boolean | — | Whether the page can be deleted |
generator | string | — | For generated pages, the source that produces them |
formId | string | — | For form pages, the managed form rendered by this page |
arrayKeys | array | — | Schema for repeatable array-based content (see below) |
textKeys | array | — | Deprecated (v3+). Retained only for v1/v2 backward compatibility |
Page Types
Static
User-created content pages such as /about or /services.
yaml
- slug: about
path: /about
type: static
title: About Us
deletable: trueIndex
Collection landing pages such as /blogs. Typically protected.
yaml
- slug: blogs
path: /blogs
type: index
title: Blog
deletable: falseDynamic
Pages generated from data, using a :param path segment and a generator that produces the individual routes.
yaml
- slug: topics
path: /topics/:topic
type: dynamic
title: Topic Pages
deletable: false
generator: docs/topics/[topic].paths.tsBlog and Event
Content pages backed by a WYSIWYG editor. blog pages are managed through the blog CMS; event pages carry event metadata alongside their content.
yaml
- slug: events
path: /events
type: event
title: Events
deletable: falseForm
Pages that render a managed form definition, referenced by formId.
yaml
- slug: contact
path: /contact
type: form
title: Contact
deletable: true
formId: contact-primaryArray Keys
For repeatable content (FAQs, service lists, and similar), define an arrayKeys schema instead of enumerating every array index by hand:
yaml
- slug: services
path: /services
type: static
title: Services
arrayKeys:
- key: services
itemSchema:
- title
- description
minItems: 1
maxItems: 12Each array item exposes the fields in itemSchema; minItems (default 0) and maxItems (default 100) bound how many items are allowed.
Snapshot Settings
The optional snapshot block controls how page snapshots are captured for the visual page editor:
yaml
snapshot:
viewport:
width: 1280
height: 800
waitAfterLoad: 500
captureFullPage: trueText Keys
Text keys follow a {page}.{section}.{element} naming convention, for example home.hero.title. In v3 configs they are not declared in pages.yaml — they are discovered automatically during snapshot capture and the editable values are stored in .dcs/content.yaml. Keys shared across every page (navigation, footer, and so on) can be listed under the root globalTextKeys.
Protected Pages
Give system pages deletable: false so they can't be removed from the portal. A new site is scaffolded with protected home (static), blogs (index), and topics (dynamic) pages by default.
Excluded Paths
Use excluded to keep individual, data-generated URLs out of management — for example, individual blog posts, which are managed through the blog CMS rather than as standalone pages:
yaml
excluded:
- /blogs/**Validation
Validate a site's .dcs configuration (including pages.yaml) with the CLI:
bash
dcs validateSlug Rules
- Lowercase only
- Hyphens for word separation
- No special characters
- Unique across all pages
Path Rules
- Must start with
/ - Dynamic segments use
:paramsyntax - Must be unique for static pages
Creating Pages via the Portal
When you create a page through the portal:
- A new entry is added to
pages.yaml - A page file is created from a template
- A development request is opened
- The AI coding agent implements the content, with human review before it ships
Troubleshooting
Page Not Appearing in the Portal
- Verify
pages.yamlsyntax - Check that the slug is unique
- Ensure the path is valid
- Run
dcs validate
Dynamic Page Issues
- Confirm the path includes a
:paramsegment - Confirm a
generatorproduces the routes - Ensure the data source provides the parameter values
Next Steps
- site.yaml — Site identity configuration
- Text Editing — Portal text management
- Sites Setup — Full integration guide
