Page operations

6 operations named page.*. Every one runs in a batch through apply_ops, dry_run_ops, the CLI or the admin.

Updated
OperationWhat it doesPermissionConfirmation
page.readRead a page row: slug, title, status, frame and SEO fields.site.readnone
page.createCreate a page with an empty tree.site.structurenone
page.updatePatch page fields as { pageId, patch }; patch.status: "published" marks a draft page for the next site publish.site.editnone
page.deleteDelete a page and its tree.site.structuredestructive
page.forkTemplateFork a theme template into an editable site page row.site.structurenone
page.setPasswordProtect a page with a password, change it, or remove it with password: null.site.editnone

page.read

Read a page row: slug, title, status, frame and SEO fields. Page validation and ownership checks apply.

permission: site.readreads onlyclass: read

Example input

{
  "pageId": "6f1d2c3b-4a59-4e8d-9c7b-1a2b3c4d5e6f"
}

Input

FieldTypeRequiredNotes
pageIdstringyesAt least 1 character.

Output

FieldTypeRequiredNotes
pageobjectyes
page.slugstringyesAt least 1 character.
page.titlerecord of stringyes
page.framestringyes
page.dynamicbooleanyes
page.positionintegeryes
page.parentIdstring | nullyes
page.requireAuthbooleanyes
page.requiredRolesarray of stringnoAt most 50 items.
page.metarecord of any JSONyes
page.pageTypestringnoOne of "static", "blog-index", "article", "brand-canvas", "template", "region", "dynamic", "component".
page.templateIdstring | nullno
page.collectionKeystring | nullno
page.statusstringnoOne of "draft", "published".
page.authorUserIdstring | nullno
page.authorNamestring | nullno
page.featuredImageIdstring | nullno
page.excerptrecord of string | nullno
page.metaTitlerecord of string | nullno
page.metaDescriptionrecord of string | nullno
page.ogImageIdstring | nullno
page.noIndexbooleanno
page.canonicalUrlstring | nullno
page.idstringyes
page.passwordProtectedbooleanno
page.publishedAtstring | nullno
page.createdAtstringyes
page.updatedAtstringyes
page.treeobjectno
warningsarray of stringno

Fields nested deeper are in the output schema that discover_operations answers with outputSchemas: true.

Try it

yarn splash page.read '{"pageId":"6f1d2c3b-4a59-4e8d-9c7b-1a2b3c4d5e6f"}' --dry-run

page.create

Create a page with an empty tree. status defaults to draft; a draft page stays out of the site publish, so pass status: "published" for a page the next publication.publish should serve. Fill the tree with tree.commit in the same batch: read the new root id with tree.read through a $ref to this operation's page.id. A section's anchor is the node field anchor in that tree, not a page field, meta.anchor or props.anchor. A pageType: "dynamic" page names a collection in collectionKey and is the detail page of its items: it answers /<slug>/<item slug> in each locale, and its tree binds the item. Page validation and ownership checks apply.

permission: site.structurewrites: pagesclass: transactionundo: yes

Example input

{
  "slug": "studio",
  "title": {
    "en-US": "Studio"
  },
  "status": "published"
}

Input

FieldTypeRequiredNotes
slugstringyesAt least 1 character.
titlerecord of stringyes
framestringno
dynamicbooleanno
positionintegerno
parentIdstring | nullno
requireAuthbooleanno
requiredRolesarray of stringnoAt most 50 items.
metarecord of any JSONno
pageTypestringnoOne of "static", "blog-index", "article", "dynamic".
templateIdstring | nullno
collectionKeystring | nullno
statusstringnoOne of "draft", "published".
authorUserIdstring | nullno
authorNamestring | nullno
featuredImageIdstring | nullno
excerptrecord of string | nullno
metaTitlerecord of string | nullno
metaDescriptionrecord of string | nullno
ogImageIdstring | nullno
noIndexbooleanno
canonicalUrlstring | nullno
publishedAtstring (date-time) | nullno

Output

FieldTypeRequiredNotes
pageobjectyes
page.slugstringyesAt least 1 character.
page.titlerecord of stringyes
page.framestringyes
page.dynamicbooleanyes
page.positionintegeryes
page.parentIdstring | nullyes
page.requireAuthbooleanyes
page.requiredRolesarray of stringnoAt most 50 items.
page.metarecord of any JSONyes
page.pageTypestringnoOne of "static", "blog-index", "article", "brand-canvas", "template", "region", "dynamic", "component".
page.templateIdstring | nullno
page.collectionKeystring | nullno
page.statusstringnoOne of "draft", "published".
page.authorUserIdstring | nullno
page.authorNamestring | nullno
page.featuredImageIdstring | nullno
page.excerptrecord of string | nullno
page.metaTitlerecord of string | nullno
page.metaDescriptionrecord of string | nullno
page.ogImageIdstring | nullno
page.noIndexbooleanno
page.canonicalUrlstring | nullno
page.idstringyes
page.passwordProtectedbooleanno
page.publishedAtstring | nullno
page.createdAtstringyes
page.updatedAtstringyes
page.treeobjectno
warningsarray of stringno

Fields nested deeper are in the output schema that discover_operations answers with outputSchemas: true.

Try it

yarn splash page.create '{"slug":"studio","title":{"en-US":"Studio"},"status":"published"}' --dry-run

page.update

Patch page fields as { pageId, patch }; patch.status: "published" marks a draft page for the next site publish. Page validation and ownership checks apply.

permission: site.editwrites: pagesclass: transactionundo: yes

Example input

{
  "pageId": "6f1d2c3b-4a59-4e8d-9c7b-1a2b3c4d5e6f",
  "patch": {
    "title": {
      "en-US": "Studio and team"
    },
    "status": "published"
  }
}

Input

FieldTypeRequiredNotes
pageIdstringyesAt least 1 character.
patchobjectyes
patch.slugstringnoAt least 1 character.
patch.titlerecord of stringno
patch.framestringno
patch.dynamicbooleanno
patch.positionintegerno
patch.parentIdstring | nullno
patch.requireAuthbooleanno
patch.requiredRolesarray of stringnoAt most 50 items.
patch.metarecord of any JSONno
patch.pageTypestringnoOne of "static", "blog-index", "article", "brand-canvas", "template", "region", "dynamic", "component".
patch.templateIdstring | nullno
patch.collectionKeystring | nullno
patch.statusstringnoOne of "draft", "published".
patch.authorUserIdstring | nullno
patch.authorNamestring | nullno
patch.featuredImageIdstring | nullno
patch.excerptrecord of string | nullno
patch.metaTitlerecord of string | nullno
patch.metaDescriptionrecord of string | nullno
patch.ogImageIdstring | nullno
patch.noIndexbooleanno
patch.canonicalUrlstring | nullno

Output

FieldTypeRequiredNotes
pageobjectyes
page.slugstringyesAt least 1 character.
page.titlerecord of stringyes
page.framestringyes
page.dynamicbooleanyes
page.positionintegeryes
page.parentIdstring | nullyes
page.requireAuthbooleanyes
page.requiredRolesarray of stringnoAt most 50 items.
page.metarecord of any JSONyes
page.pageTypestringnoOne of "static", "blog-index", "article", "brand-canvas", "template", "region", "dynamic", "component".
page.templateIdstring | nullno
page.collectionKeystring | nullno
page.statusstringnoOne of "draft", "published".
page.authorUserIdstring | nullno
page.authorNamestring | nullno
page.featuredImageIdstring | nullno
page.excerptrecord of string | nullno
page.metaTitlerecord of string | nullno
page.metaDescriptionrecord of string | nullno
page.ogImageIdstring | nullno
page.noIndexbooleanno
page.canonicalUrlstring | nullno
page.idstringyes
page.passwordProtectedbooleanno
page.publishedAtstring | nullno
page.createdAtstringyes
page.updatedAtstringyes
page.treeobjectno
warningsarray of stringno

Fields nested deeper are in the output schema that discover_operations answers with outputSchemas: true.

Try it

yarn splash page.update '{"pageId":"6f1d2c3b-4a59-4e8d-9c7b-1a2b3c4d5e6f","patch":{"title":{"en-US":"Studio and team"},"status":"published"}}' --dry-run

page.delete

Delete a page and its tree. Page validation and ownership checks apply.

permission: site.structurewrites: pagesclass: transactionconfirm: destructiveundo: yes

Example input

{
  "pageId": "6f1d2c3b-4a59-4e8d-9c7b-1a2b3c4d5e6f"
}

Input

FieldTypeRequiredNotes
pageIdstringyesAt least 1 character.

Output

FieldTypeRequiredNotes
successtrueyes

Needs confirmed: ["destructive"] on the batch, which the single-operation CLI form does not set: put it in a batch file and run yarn splash apply <file> --dry-run.

page.forkTemplate

Fork a theme template into an editable site page row. Page validation and ownership checks apply.

permission: site.structurewrites: pagesclass: transactionundo: yes

Example input

{
  "templateId": "page"
}

Input

FieldTypeRequiredNotes
templateIdstringyesAt least 1 character.

Output

FieldTypeRequiredNotes
pageobjectyes
page.slugstringyesAt least 1 character.
page.titlerecord of stringyes
page.framestringyes
page.dynamicbooleanyes
page.positionintegeryes
page.parentIdstring | nullyes
page.requireAuthbooleanyes
page.requiredRolesarray of stringnoAt most 50 items.
page.metarecord of any JSONyes
page.pageTypestringnoOne of "static", "blog-index", "article", "brand-canvas", "template", "region", "dynamic", "component".
page.templateIdstring | nullno
page.collectionKeystring | nullno
page.statusstringnoOne of "draft", "published".
page.authorUserIdstring | nullno
page.authorNamestring | nullno
page.featuredImageIdstring | nullno
page.excerptrecord of string | nullno
page.metaTitlerecord of string | nullno
page.metaDescriptionrecord of string | nullno
page.ogImageIdstring | nullno
page.noIndexbooleanno
page.canonicalUrlstring | nullno
page.idstringyes
page.passwordProtectedbooleanno
page.publishedAtstring | nullno
page.createdAtstringyes
page.updatedAtstringyes
page.treeobjectno
warningsarray of stringno

Fields nested deeper are in the output schema that discover_operations answers with outputSchemas: true.

Try it

yarn splash page.forkTemplate '{"templateId":"page"}' --dry-run

page.setPassword

Protect a page with a password, change it, or remove it with password: null. A visitor sees the password form instead of the page until they enter it; members are asked too. The password is stored hashed and never answered: page answers say only passwordProtected. Like the other page fields it reaches the public site with the next publish. Run it alone in a batch: the input is redacted from the history and the audit log, and the change is not undone.

permission: site.editwrites: pagesclass: transactionundo: explicit recovery

Example input

{
  "pageId": "6f1d2c3b-4a59-4e8d-9c7b-1a2b3c4d5e6f",
  "password": "press-preview-2026"
}

Input

FieldTypeRequiredNotes
pageIdstringyesAt least 1 character.
passwordstring | nullyes

Output

FieldTypeRequiredNotes
pageobjectyes
page.slugstringyesAt least 1 character.
page.titlerecord of stringyes
page.framestringyes
page.dynamicbooleanyes
page.positionintegeryes
page.parentIdstring | nullyes
page.requireAuthbooleanyes
page.requiredRolesarray of stringnoAt most 50 items.
page.metarecord of any JSONyes
page.pageTypestringnoOne of "static", "blog-index", "article", "brand-canvas", "template", "region", "dynamic", "component".
page.templateIdstring | nullno
page.collectionKeystring | nullno
page.statusstringnoOne of "draft", "published".
page.authorUserIdstring | nullno
page.authorNamestring | nullno
page.featuredImageIdstring | nullno
page.excerptrecord of string | nullno
page.metaTitlerecord of string | nullno
page.metaDescriptionrecord of string | nullno
page.ogImageIdstring | nullno
page.noIndexbooleanno
page.canonicalUrlstring | nullno
page.idstringyes
page.passwordProtectedbooleanno
page.publishedAtstring | nullno
page.createdAtstringyes
page.updatedAtstringyes
page.treeobjectno
warningsarray of stringno

Fields nested deeper are in the output schema that discover_operations answers with outputSchemas: true.

Try it

yarn splash page.setPassword '{"pageId":"6f1d2c3b-4a59-4e8d-9c7b-1a2b3c4d5e6f","password":"press-preview-2026"}' --dry-run

Generated from the operation registry and the MCP tool catalogue (source 3529441cd9df8ff0).

Something wrong on this page? Write to docs@librettocms.com.

Libretto docs

Colophon. These docs are a Libretto site: 68 pages in two languages, 20 guide pages imported from Markdown and 41 reference pages generated from the operation registry. Set in Softcore, with code in IBM Plex Mono. Its outline:

/ Libretto docs /start Get started /start/request-access Request access /start/workspace Your workspace /start/first-site Your first site /start/invite-a-client Invite a client /start/connect-claude Connect Claude to Libretto /build Build /build/first-page Build a page /build/layers-and-canvas Layers and canvas /build/site-components Site components /design-system Design system /design-system/tokens Colours, space and themes /design-system/components Components and variants /design-system/fonts Typography and fonts /motion Motion /motion/scenes Scenes and recipes /motion/image-sequences Image sequences /motion/reduced-motion Reduced motion /publish Publish /publish/languages Site languages /publish/versions Publish and versions /publish/members-and-forms Members and forms /publish/domains Domains /handover Hand a site to a client /glossary Glossary /agents Agents and API /agents/mcp MCP server /agents/cli CLI /agents/batches Batches /agents/errors Errors and findings /agents/operations Operations /search Search