skills/canvas-page-definition/SKILL.md
Start here for any Canvas page-spec task. Use for create, modify, refactor, review, migrate, or validate work on page JSON files that sync with Canvas and render in Workbench. Establishes the canonical Canvas page-spec contract, including placement, structure, format constraints, and validation.
npx skillsauth add drupal-canvas/skills canvas-page-definitionInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
A Canvas page is a JSON page spec stored in the repository's configured
pagesDir.
Workbench uses these files for local page previews, and the Canvas CLI
push/pull workflow uses them to sync pages between the local project and
Drupal Canvas.
Page specs should fully mirror what authors can build in Drupal Canvas.
Every Canvas page MUST satisfy all checks below:
pagesDir in
canvas.config.json; default ./pages)titlepath that starts with / and is unique within the
projectelements object with at least one elementelements includes a discovered component typeslots entries reference element IDs defined in the same fileIf any item is missing, the page is incomplete for Canvas usage.
Author the canonical local page specs in the configured pages directory
(pagesDir in canvas.config.json). If pagesDir is not set, Workbench
defaults to the top-level pages/ directory.
<pages-dir>/<page-name>.jsontitle inside the JSON file for the actual page titleExamples:
<pages-dir>/homepage.json<pages-dir>/about-us.jsonTreat files in the configured pagesDir as the source of truth for local page
definitions that can be previewed in Workbench and synced with Canvas via the
CLI.
Authored page work is incomplete unless the page is previewable from the
configured pagesDir and ready for validation.
Each page file must be a JSON object with:
title: the actual page titlepath: the page's URL path (e.g., /about). Must start with / and be
unique within the project. Other pages link to this page using this value.elements: an object of authored page elementsThe page file may also include:
description: a short plain-text summary of the page. Surfaced as page
metadata (e.g., for listings or SEO). Leave as an empty string if not set.Each entry in elements must include:
type: a discovered component typeEach entry may also include:
props: root props for that elementslots: a map of slot names to arrays of element IDs from the same fileWorkbench preserves elements insertion order when building the page. Put
top-level sections in the order you want them rendered.
Use the discovered machine-readable component type for each element, such as
card, heading, or js.hero, depending on what Workbench finds in the local
project.
To link to another page in the project, reference the target page's path.
{
"title": "About",
"path": "/about",
"description": "",
"elements": {
"hero": {
"type": "js.hero",
"props": {
"heading": "About us",
"text": "Learn how our team plans, builds, and ships Canvas experiences.",
"layout": "left_aligned"
}
},
"spacer-lg": {
"type": "js.spacer",
"props": {
"height": "large"
}
},
"body-section": {
"type": "js.section",
"props": {
"width": "normal"
},
"slots": {
"content": ["body-copy"]
}
},
"body-copy": {
"type": "js.text",
"props": {
"content": "<p>Canvas pages should use real component composition rather than custom page wrappers.</p>"
}
}
}
}
Use stable, descriptive element IDs unless you are intentionally preserving IDs from another source such as an exported Canvas page.
When a component prop is defined as an image in component.yml, page JSON must
pass that prop as a single image object. Match the component prop name exactly
and use the Canvas image shape inside props.
{
"type": "js.card",
"props": {
"image": {
"src": "https://placehold.co/400x300/png",
"alt": "Card placeholder image",
"width": "400",
"height": "300"
},
"heading": "Featured card"
}
}
Supported authored page image sources:
http:// or https:// URLsdata:image/... URLsDo not use local file paths in page JSON. CLI media upload from local files is not supported.
If page media reconciliation or page sync adds resolved image data such as
width, height, or _provenance, preserve that data unless you are
intentionally changing the image source.
The page-spec format only supports discovered component elements plus their
props and slots.
That means page specs cannot directly represent:
PageLayout<div> or <section>className-driven spacing or custom wrapper stylingIf you need a layout primitive, look for an existing component first. If none exists, create it as a component before using it in a page spec.
Validate every authored page before finishing.
npx canvas validate
testing
Use for any task touching site chrome — header, footer, sidebar, or global navigation that repeats across pages — and for any region-spec work (create, modify, review, validate region JSON, or the project-level layout component). Also load when a task creates or edits multiple pages that share chrome, or asks for a "site" or "navigation between pages"; shared chrome belongs in regions, never inlined into page JSON.
content-media
Create and modify content templates that map Drupal content entities to Canvas component layouts. Use when asked to (1) Create a new content template, (2) Modify an existing content template, (3) Add or change entity field mappings in a template, (4) Compose components in a content template via slots. Content templates live in the configured `contentTemplatesDir` (default `content-templates/`) and define how Drupal entity types, bundles, and view modes render as Canvas component trees.
tools
Plans and builds Drupal Canvas navigation UI (main nav, footer links, sidebar nav, mobile drawers, breadcrumbs) using design decomposition for structure and props/slots, then JSON:API menu or page-context patterns from canvas-data-fetching. Use when the user asks for navigation, header or footer links, menus, menu_items, mobile nav, or breadcrumb trails. Run after canvas-design-decomposition for layout and API sketches; follow canvas-data-fetching for SWR, JsonApiClient, sortMenu, and menu fallbacks.
development
Plans structure for a component library with props/slots and right-sized component granularity. Run before building or adding Canvas components (new `src/components/` folders, component.yml, React), or for plan-only / breakdown-only work, whenever UI must map to a coherent tree. Mandatory for every new Figma frame or greenfield screen—repository drafts do not replace phases A–G.