Patterns
Reusable compositions of components, one level up from a single component.
A pattern is a saved composition of component blocks: an ordered arrangement of existing components with their prop values, built and saved from the Playground rather than declared as its own component. Where a component is a single reusable unit, a pattern is "here's how several of them fit together", a layout, not a primitive.
Shape
handoff_pattern holds: id, path, title, description, group, tags, a components
list (which component blocks it references), and a data blob (the full composition). source
records how it got here: playground (built interactively), build, import, or ai. An
optional userId records the creator/owner for playground-saved patterns.
A second set of columns carries the sharing/review lifecycle:
| Column | Values |
|---|---|
kind | What the row is, as opposed to where it came from: page, template, or brief (brief is transitional). Split out of source, which was answering two questions at once. |
status | prototype | draft | review | approved | archived. Drives the review queue and handoff_review_page. |
visibility | private | shared | team | public. Never changed by a review decision — promoting a page to a wider audience stays a separate, deliberate act. |
shareLinkToken | The guest share link a page was created through. Scopes a guest to their own submission, since guest pages are owned by the link's creator. Deliberately outlives the link, so there's no FK. |
templateId / submittedByEmail | For a built page: the brief it came from (drives the review diff) and the author's email for state-change notifications. |
separately in handoff_pattern_change, one append-only row per create/update/delete, each | |
| carrying a human message and a lazy AI summary, the same "why" model components and tokens use | |
| — see Changelog / audit. |
Three surfaces
| Surface | Where |
|---|---|
| UI | /patterns (browse/search) and /playground (the interactive builder) for general use; /system/pattern and /system/pattern/[pattern] for the developer-facing catalog/detail view, see Registry → Stakeholder-facing UI routes. |
| REST | GET /api/handoff/patterns (+ /{id}, /{id}/clone), filterable by q/group/source on list, see API → /api/handoff. Also travels through POST /api/sync/upload / GET /api/sync/changes as a pattern-type sync change when pushed/pulled from a workspace (handoff-app push --patterns <ids>), see API → /api/sync. |
| MCP | Confusingly named in the tool catalog: patterns are exposed under the Pages & Compositions tool family, not a pattern-named one — handoff_list_pages, handoff_get_page, handoff_create_page (sync:write), handoff_update_page (sync:write). The tool catalog itself calls this out: "'Pages' here means playground pages (patterns) — saved component-block compositions, distinct from markdown doc pages" (see Concepts → Pages / docs for that other, unrelated "pages" concept). See MCP → Tool catalog § Pages & Compositions. |
Two unrelated concepts share the word 'page'
MCP's "Pages & Compositions" tools operate on patterns (this page). MCP's separate
"Documentation" tool family (handoff_list_doc_pages, etc.) operates on markdown doc pages
, see Pages / docs. The REST layer avoids this collision (patterns
live under /api/handoff/patterns, doc pages under /api/handoff/pages); only the MCP naming
overlaps. Worth keeping straight when reading the tool catalog.