docs: Make article image replacement setup explicit

This commit is contained in:
Oleg Isonen committed 2026-09-09 11:10:11 +01:00
1 parent d307c8ba3d
commit f90e39cfcc
11 files changed
+112 -30

No files matched your search

@@ -205,7 +205,7 @@ featureImage:
$ref: ./images/feature.png
```
To use frontmatter in the designed part of a Content Block, [bind](../foundations/variables.md) a property or text value to the Content Block's **document** variable. For example, bind a heading to `document.frontmatter.title`, an Image source to `document.frontmatter.featureImage.src`, and its alternative text to `document.frontmatter.featureImage.description`. This uses the image's Asset description instead of duplicating alternative text in frontmatter. Fields authored directly in the connected MDX file can be edited on the canvas and through supported Settings controls in Content mode; edits save back to that file. Direct bindings through a loaded Markdown or MDX `$ref` ending in `#frontmatter` save to the referenced file, with its write permissions enforced. Shared-record edits affect every document using that record. Computed expressions, JSON/body references, and resolved image metadata remain read-only.
To use frontmatter in the designed part of a Content Block, [bind](../foundations/variables.md) a property or text value to the Content Block's **document** variable. For example, bind a heading to `document.frontmatter.title`, an Image source to `document.frontmatter.featureImage.src`, and its alternative text to `document.frontmatter.featureImage.description`. This uses the image's Asset description instead of duplicating alternative text in frontmatter. Fields authored directly in the connected MDX file can be edited on the canvas and through supported Settings controls in Content mode; edits save back to that file. Direct bindings through a loaded Markdown or MDX `$ref` ending in `#frontmatter` save to the referenced file, with its write permissions enforced. Shared-record edits affect every document using that record. Computed expressions and JSON/body references remain read-only. Image replacement is supported: a direct Image source binding with `mode:"readwrite"` lets the picker replace the frontmatter `$ref`, while shared Asset metadata is edited in Asset settings.
**Check every article field**
+2 -2
View File
@@ -189,9 +189,9 @@ Use the dedicated connect, switch, inspect, edit, update-frontmatter, reload, an
`renderScope` is any non-empty stable identity for one rendered occurrence, such as `page:/articles/example`. It does not load that page, its route parameters, or its resource results. To connect a result-one Assets resource, run `preview-asset-query` with concrete values, keep the saved source expression such as `post.data.id`, and supply the previewed item for this occurrence with `variables:{"post":{"data":{"id":"<mdxAssetId>"}}}`. The operation validates that concrete Asset while persisting the dynamic expression.
A source edit replaces the complete MDX document. A frontmatter update replaces the complete frontmatter property map. Inspect the current source first and preserve everything the user did not ask to change. Store frontmatter images as exact `$ref` objects, bind Image sources to their resolved `.src`, and bind alt properties to their Asset `.description`. Use `update-content-block-frontmatter` for MCP frontmatter edits. MDX-rendered elements are not persistent instance targets for generic `bind-props` or `update-text` calls. Preserve existing `mode:"readwrite"` bindings when encountered; they are valid only for exact direct paths into the connected document's frontmatter. Direct bindings through a loaded Markdown or MDX `$ref` ending in `#frontmatter` save to the referenced file, with its write permissions enforced. Shared-record edits affect every document using that record. Computed expressions, JSON/body references, and resolved image metadata remain read-only.
A source edit replaces the complete MDX document. A frontmatter update replaces the complete frontmatter property map. Inspect the current source first and preserve everything the user did not ask to change. Store frontmatter images as exact `$ref` objects. Bind editable Image sources to their resolved `.src` with explicit `binding.mode:"readwrite"`; omitting the mode leaves the image visible but not replaceable in Content mode. Bind alt properties to their Asset `.description` with `mode:"read"`. Use `update-content-block-frontmatter` for MCP frontmatter edits. MDX-rendered elements are not persistent instance targets for generic `bind-props` or `update-text` calls. Preserve existing `mode:"readwrite"` bindings when encountered; they are valid only for exact direct paths into the connected document's frontmatter. Direct bindings through a loaded Markdown or MDX `$ref` ending in `#frontmatter` save to the referenced file, with its write permissions enforced. Shared-record edits affect every document using that record. Computed expressions and JSON/body references remain read-only. Image replacement is supported: a direct Image source binding with `mode:"readwrite"` lets the picker replace the frontmatter `$ref`, while shared Asset metadata is edited in Asset settings.
For an editable MDX article, use the resource to select the Content Block's source Asset (`post.data.id`), then bind article fields inside the block to its document parameter (`document.frontmatter.title`), not query-result properties. Inspect the actual document variable name first. Create writable bindings explicitly: `update-text` uses `expressionBindingMode:"readwrite"`; `bind-props` uses `binding.mode:"readwrite"`. These generic tools target persistent designed instances, such as a header outside the MDX body, not MDX-generated instances. The MDX body is editable through its source mapping; merely placing static or query-bound content inside the block does not make it editable. Use exact direct paths; property access is already safe. Direct bindings through a loaded Markdown or MDX `$ref` ending in `#frontmatter` save to the referenced file, with its write permissions enforced. Shared-record edits affect every document using that record. Computed expressions, JSON/body references, and resolved image metadata remain read-only. Follow the complete article editability checklist below before handoff.
For an editable MDX article, use the resource to select the Content Block's source Asset (`post.data.id`), then bind article fields inside the block to its document parameter (`document.frontmatter.title`), not query-result properties. Inspect the actual document variable name first. Create writable bindings explicitly: `update-text` uses `expressionBindingMode:"readwrite"`; `bind-props` uses `binding.mode:"readwrite"`. These generic tools target persistent designed instances, such as a header outside the MDX body, not MDX-generated instances. The MDX body is editable through its source mapping; merely placing static or query-bound content inside the block does not make it editable. Use exact direct paths; property access is already safe. Direct bindings through a loaded Markdown or MDX `$ref` ending in `#frontmatter` save to the referenced file, with its write permissions enforced. Shared-record edits affect every document using that record. Computed expressions and JSON/body references remain read-only. Image replacement is supported: a direct Image source binding with `mode:"readwrite"` lets the picker replace the frontmatter `$ref`, while shared Asset metadata is edited in Asset settings. Follow the complete article editability checklist below before handoff.
### Content Block completion checklist
@@ -229,6 +229,32 @@ test("documents MCP examples with current tool input fields", () => {
}
});
test("the article image recipe enables reference replacement without making shared metadata writable", () => {
const prefix = "MCP tool: bind-props ";
const bindings = useCaseScenarios
.flatMap(({ commands }) => commands)
.filter((command) => command.startsWith(prefix))
.flatMap((command) => JSON.parse(command.slice(prefix.length)).bindings);
const source = bindings.find(
({ name, binding }) =>
name === "src" &&
binding.value === "document.frontmatter.featureImage.src"
);
expect(source?.binding).toEqual({
type: "expression",
value: "document.frontmatter.featureImage.src",
mode: "readwrite",
});
const alternativeText = bindings.find(
({ instanceId, name }) => instanceId === source.instanceId && name === "alt"
);
expect(alternativeText?.binding).toEqual({
type: "expression",
value: "document.frontmatter.featureImage.description",
mode: "read",
});
});
test("does not document client-supplied generated ids for create operations", () => {
const forbiddenGeneratedIdFieldsByCommand = new Map(
builderRuntimeOperations.flatMap((operation) => {
+4 -4
View File
@@ -2,15 +2,15 @@
// Edit markdown files in src/docs instead.
export const cliDocs = {
"api-use-cases":
'# CLI API Use Cases\n\n## Link/configure one project\n\nCommands:\n\n- webstudio init --link <api-share-link> --json\n\nNotes:\n\n- Writes local project id and global origin/token config.\n\n## Import synced project bundle into another project\n\nCommands:\n\n- webstudio sync\n- webstudio import --to <destination-share-link>\n- MCP tool: import {"to":"<destination-share-link>"}\n\nNotes:\n\n- Imports local `.webstudio/data.json` into the destination project.\n- Destination share link must allow build/import access.\n- Use `--skip-assets` only when asset rows and files should not be imported.\n\n## Identify current token\n\nCommands:\n\n- MCP tool: whoami {}\n\n## Check token permissions\n\nCommands:\n\n- webstudio permissions --json\n\n## Inspect project/build/version\n\nCommands:\n\n- MCP tool: inspect {}\n- MCP tool: snapshot {"include":["pages","instances","styles"]}\n\n## Discover CLI/API capabilities\n\nCommands:\n\n- webstudio schema api\n- webstudio schema mcp\n- webstudio man --json\n- webstudio man llm --json\n- MCP tool: meta.index {}\n- MCP tool: meta.guide {"brief":"Create a pricing page"}\n- MCP tool: meta.get-more-tools {"brief":"update-styles"}\n- webstudio mcp list-resources\n- webstudio mcp read-resource webstudio://project/guide\n- webstudio mcp read-resource webstudio://project/expressions\n\nNotes:\n\n- Use `webstudio schema mcp` for a compact machine-readable MCP tool overview. Add `--verbose` or use focused `meta.get-more-tools` calls only when exact input schemas are needed.\n- Use focused MCP tools for discovery first: `meta.index`, `meta.guide`, `meta.get-more-tools`, `components.list`, `components.summary`, `components.search`, `components.get`, `templates.list`, and `templates.get`. Protocol clients can use `resources/list` and `resources/read`; shell agents can use `webstudio mcp list-resources` and `webstudio mcp read-resource <uri>`. Read longer resources such as `webstudio://project/tools` and `webstudio://project/components` only when focused tools are insufficient.\n- `components.summary` returns counts by default; request `{"detail":"components","limit":20}` for paginated entries. Registry list tools return compact metadata, while `components.get` and `templates.get` return focused full details.\n- Read `webstudio://project/expressions` before authoring unfamiliar computed text, prop bindings, resource expressions, actions, or Collection item bindings.\n- From a shell, call one MCP tool with the shortcut form `webstudio <tool> \'<json>\'`, for example `webstudio components.summary`. The explicit equivalent is `webstudio mcp single-op-call <tool> \'<json>\'`. Use `--input-file` for large payloads.\n\n## Inspect external shadcn registry items\n\nCommands:\n\n- webstudio registry inspect --source https://example.com/r/registry.json --item button --json\n- webstudio registry inspect --source ./registry.json --item dialog --json\n- webstudio registry inspect --source https://example.com/r/button.json --json\n\nNotes:\n\n- Reads a local or remote registry item without installing files or changing the configured Webstudio project.\n- Returns the item name, description, package and registry dependencies, file paths/targets, available docs, and a read-only compatibility report.\n- The report explicitly says whether installation or editable-component conversion is supported, lists declared requirements and manual steps, and says when arbitrary source code was not analyzed.\n- This is an inspection step only. It does not install files or change the configured project.\n\n## Understand what MCP can do\n\nCommands:\n\n- webstudio man mcp\n- MCP tool: meta.index {}\n- MCP tool: meta.guide {"brief":"What can Webstudio MCP do?"}\n\nMCP lets agents work on one configured Webstudio project. Agents can:\n\n- Inspect the linked project, token permissions, and latest editable build.\n- Read selected project data for audits, migrations, and repair.\n- Search values and ids across every Builder namespace without sending full project data to the model.\n- Audit accessibility, security, SEO, performance settings, unused assets, ineffective Collection styles, and unused or duplicate style data.\n- Create and edit pages, folders, redirects, breakpoints, and page templates.\n- Create pages from reusable templates.\n- Update page metadata, SEO fields, auth settings, and marketplace metadata.\n- Insert components and styled JSX sections.\n- Create data-driven lists, grids, cards, and similar repeated UI from array or object data in one Collection operation.\n- Move, copy, wrap, unwrap, convert, rename, retag, and delete elements.\n- Update text, rich text, props, bindings, and actions.\n- Create and update local styles, design tokens, style sources, and CSS variables.\n- Create static data variables and JSON variables.\n- Create HTTP, GraphQL, and system resources.\n- Use system resources for sitemap, current date, and assets.\n- Bind resources to rendered data or form/action props.\n- Manage nest Line truncated
'# CLI API Use Cases\n\n## Link/configure one project\n\nCommands:\n\n- webstudio init --link <api-share-link> --json\n\nNotes:\n\n- Writes local project id and global origin/token config.\n\n## Import synced project bundle into another project\n\nCommands:\n\n- webstudio sync\n- webstudio import --to <destination-share-link>\n- MCP tool: import {"to":"<destination-share-link>"}\n\nNotes:\n\n- Imports local `.webstudio/data.json` into the destination project.\n- Destination share link must allow build/import access.\n- Use `--skip-assets` only when asset rows and files should not be imported.\n\n## Identify current token\n\nCommands:\n\n- MCP tool: whoami {}\n\n## Check token permissions\n\nCommands:\n\n- webstudio permissions --json\n\n## Inspect project/build/version\n\nCommands:\n\n- MCP tool: inspect {}\n- MCP tool: snapshot {"include":["pages","instances","styles"]}\n\n## Discover CLI/API capabilities\n\nCommands:\n\n- webstudio schema api\n- webstudio schema mcp\n- webstudio man --json\n- webstudio man llm --json\n- MCP tool: meta.index {}\n- MCP tool: meta.guide {"brief":"Create a pricing page"}\n- MCP tool: meta.get-more-tools {"brief":"update-styles"}\n- webstudio mcp list-resources\n- webstudio mcp read-resource webstudio://project/guide\n- webstudio mcp read-resource webstudio://project/expressions\n\nNotes:\n\n- Use `webstudio schema mcp` for a compact machine-readable MCP tool overview. Add `--verbose` or use focused `meta.get-more-tools` calls only when exact input schemas are needed.\n- Use focused MCP tools for discovery first: `meta.index`, `meta.guide`, `meta.get-more-tools`, `components.list`, `components.summary`, `components.search`, `components.get`, `templates.list`, and `templates.get`. Protocol clients can use `resources/list` and `resources/read`; shell agents can use `webstudio mcp list-resources` and `webstudio mcp read-resource <uri>`. Read longer resources such as `webstudio://project/tools` and `webstudio://project/components` only when focused tools are insufficient.\n- `components.summary` returns counts by default; request `{"detail":"components","limit":20}` for paginated entries. Registry list tools return compact metadata, while `components.get` and `templates.get` return focused full details.\n- Read `webstudio://project/expressions` before authoring unfamiliar computed text, prop bindings, resource expressions, actions, or Collection item bindings.\n- From a shell, call one MCP tool with the shortcut form `webstudio <tool> \'<json>\'`, for example `webstudio components.summary`. The explicit equivalent is `webstudio mcp single-op-call <tool> \'<json>\'`. Use `--input-file` for large payloads.\n\n## Inspect external shadcn registry items\n\nCommands:\n\n- webstudio registry inspect --source https://example.com/r/registry.json --item button --json\n- webstudio registry inspect --source ./registry.json --item dialog --json\n- webstudio registry inspect --source https://example.com/r/button.json --json\n\nNotes:\n\n- Reads a local or remote registry item without installing files or changing the configured Webstudio project.\n- Returns the item name, description, package and registry dependencies, file paths/targets, available docs, and a read-only compatibility report.\n- The report explicitly says whether installation or editable-component conversion is supported, lists declared requirements and manual steps, and says when arbitrary source code was not analyzed.\n- This is an inspection step only. It does not install files or change the configured project.\n\n## Understand what MCP can do\n\nCommands:\n\n- webstudio man mcp\n- MCP tool: meta.index {}\n- MCP tool: meta.guide {"brief":"What can Webstudio MCP do?"}\n\nMCP lets agents work on one configured Webstudio project. Agents can:\n\n- Inspect the linked project, token permissions, and latest editable build.\n- Read selected project data for audits, migrations, and repair.\n- Search values and ids across every Builder namespace without sending full project data to the model.\n- Audit accessibility, security, SEO, performance settings, unused assets, ineffective Collection styles, and unused or duplicate style data.\n- Create and edit pages, folders, redirects, breakpoints, and page templates.\n- Create pages from reusable templates.\n- Update page metadata, SEO fields, auth settings, and marketplace metadata.\n- Insert components and styled JSX sections.\n- Create data-driven lists, grids, cards, and similar repeated UI from array or object data in one Collection operation.\n- Move, copy, wrap, unwrap, convert, rename, retag, and delete elements.\n- Update text, rich text, props, bindings, and actions.\n- Create and update local styles, design tokens, style sources, and CSS variables.\n- Create static data variables and JSON variables.\n- Create HTTP, GraphQL, and system resources.\n- Use system resources for sitemap, current date, and assets.\n- Bind resources to rendered data or form/action props.\n- Manage nest Line truncated
"manual-api":
'# Webstudio API CLI Manual\n\nThe API commands operate on the single project configured by:\n\n- .webstudio/config.json: projectId\n- global Webstudio config: origin and token\n\n- Pass --json to API/discovery commands that support it. Do not add --json to top-level commands unless their help/schema documents it.\n- Never pass a project id. Commands use configured project only.\n- Read ids before writing. Do not invent ids for existing records.\n- stdout is one JSON object. stderr is diagnostics.\n- Prefer MCP semantic tools for detailed project edits. Use MCP apply-patch only when no semantic tool exists.\n\n## Start\n\n{{start}}\n\n## Read First\n\n{{readFirst}}\n\n## Project Session Cache\n\n- CLI commands use one local ProjectSession snapshot for the configured project.\n- Local-capable reads use cached namespaces when compatible and fetch only missing or stale namespaces.\n- Local-capable mutations build patches from the local snapshot, then commit with the cached build version.\n- Successful mutation commits update the local snapshot only after the remote commit succeeds.\n- Server-only commands run remotely and invalidate/refetch namespaces declared by the operation catalog.\n- Use --refresh on local-capable commands to refresh required namespaces before running.\n- Successful JSON responses include compact meta.session with operationId, buildId, version, source, committed, namespaceCounts, diagnosticCount, non-empty diagnostic summaries, and optional compatibilityVersion.\n\n## Search project data\n\nRun `webstudio search-project \'{"query":"known value"}\'` to search all Builder\nnamespaces in the local project session. Narrow it with\n`{"query":"Brand","namespaces":["styleSources","styles"]}` when only specific\nnamespaces are relevant. Results contain the current value, stable match id,\nnamespace path, owning entity, resolved references, and affected pages.\n\nValues in recognized credential fields are excluded and reported in\n`excludedSensitiveValueCount`.\n\nThe command synchronizes its required Builder namespaces, then searches locally\nand returns only matches. Namespace filters limit values matched; related\nnamespaces may still supply route and reference context, and synchronization is\nunchanged. This reduces data sent to the model, not project synchronization. It\nsearches asset metadata, not asset binaries or document contents.\n\n## CLI Capability Inventory\n\nFor a short end-consumer summary of what MCP can do, see\n`manual mcp` / `webstudio man mcp`. The MCP inventory describes the same\nproject, page, element, style, data, asset, publish, domain, and visual\nverification capabilities without internal command names.\n\n### Top-Level Commands\n\n{{topLevelCapabilityIndex}}\n\n### High-Level API Commands By Area\n\n{{apiCapabilityIndex}}\n\n### MCP Tool Operations\n\nThese are MCP tools. From a shell, call them with the shortcut form `webstudio <tool> \'<json>\'` or with the explicit form `webstudio mcp single-op-call <tool> \'<json>\'`:\n\n{{mcpOnlyCommandIndex}}\n\n## Task Recipes\n\n{{taskRecipeIndex}}\n\n## Use Case Index\n\n{{useCaseIndex}}\n\n## Known CLI Gaps\n\n{{knownCliGapIndex}}\n\n## Input File Shapes\n\n{{inputFileShapeIndex}}\n\n## Raw Patch Fallback\n\napply-patch accepts either BuildPatchTransaction[] or { "transactions": BuildPatchTransaction[] }.\n\nEach transaction has:\n\n{\n"id": "patch-transaction-label",\n"payload": [\n{\n"namespace": "projectSettings",\n"patches": [\n{ "op": "replace", "path": ["meta", "siteName"], "value": "New Site" }\n]\n}\n]\n}\n\nThe transaction id is a patch label used for optimistic synchronization. It is\nnot a Builder record id. Do not invent ids for pages, instances, props,\nbreakpoints, resources, variables, folders, assets, or other project records.\n\nPatch paths are JSON-patch-like paths into Builder store data. Map-like namespaces use ids as the first path item.\n\nSupported namespaces:\n\n- pages: redirects, page records, and folders\n- projectSettings: project-wide metadata and compiler settings\n- instances: element instances and children, including text/expression children\n- props: element props, bindings, page references, resource bindings\n- styles: CSS declarations keyed by style declaration key\n- styleSources: local style sources and reusable design tokens\n- styleSourceSelections: instance-to-style-source connections\n- dataSources: data variables, parameters, and resource data sources\n- resources: data resource definitions\n- assets: project asset records handled by the existing asset patch path\n- breakpoints: responsive breakpoints\n- marketplaceProduct: marketplace metadata\n\n## Data Sources\n\n`dataSources` is the internal Builder namespace for variables. Public API, CLI,\nand MCP tools expose it through two user-facing groups:\n\n- data variables: `list-variables`, `create-variable`, `update-variable`, and\n `delete-variable`\n- data resources: `list-resources`, `create-resource`, `update-resource`, and\Line truncated
"manual-llm":
'# Webstudio CLI Manual for LLMs\n\nUse this order. Stop only when a command returns ok:false.\n\nIf you are inside the Webstudio monorepo, the first command discovery should use\nthe local CLI exactly as `node packages/cli/local.js ...` from the repo root. Do\nnot use `packages/cli/bin.js` for local source-tree work; it is the packaged\nbuild entry and may use stale built output. Do not use `pnpm exec webstudio`,\n`pnpm --filter webstudio exec webstudio`, or a global `webstudio`: they can\nresolve an older binary.\n\nFor delegated design-system or “use every component” tasks, skip the generic warm-up sequence and start with exactly one MCP command: `webstudio workflow.next \'{"goal":"design-system-page"}\'`. Report that returned checkpoint to the parent/user and stop until continued.\n\n## Use MCP locally or optionally connect a client\n\nDo not install, register, or connect an MCP server merely because the user asks\nyou to edit a Webstudio project. If Webstudio MCP tools are already available,\nuse them. If you have shell access, use the local CLI shortcuts such as\n`webstudio meta.index` and `webstudio list-pages`; they expose the same project\noperations without changing client configuration or restarting the app.\n\nOnly when the user explicitly asks for persistent native MCP integration, run\nthe command for their client:\n\n- Claude Code: `webstudio connect claude`\n- Codex: `webstudio connect codex`\n- Cursor: `webstudio connect cursor`\n- VS Code or GitHub Copilot: `webstudio connect vscode`\n\nRun project operations from the linked project root. If the folder is not\nlinked, ask for an editable Builder share link and run\n`webstudio init --link <share-link> --json`. You can then use local CLI\nshortcuts immediately. Do not run `webstudio sync`, `webstudio connect`, or\nrestart the app unless the user specifically wants native MCP registration:\nMCP reads and edits the latest editable Builder build directly, including for\nprojects that have never been published. Treat the share link as a credential\nand do not include it in committed files, logs, screenshots, or issue reports.\n\nThe optional `connect` command verifies project access before changing client configuration. For\nClaude Code, Cursor, and VS Code it safely merges the `webstudio` server into\nthe client\'s project configuration. For Codex it runs both `codex mcp add` and\n`codex mcp get webstudio`; do not repeat those commands separately. Follow the\nreload, restart, or approval instruction printed by `connect`, then verify the\nloaded MCP connection by asking the client to use Webstudio MCP and list the\nproject pages. Use `--print` only to inspect the generated setup without\nchanging configuration or requiring project access.\n\n## Always\n\n1. webstudio permissions --json\n2. For bounded shell workflows, call MCP tools directly through the CLI shortcut, for example `webstudio meta.index` or `webstudio insert-fragment \'<json>\' --dry-run`. The explicit form `webstudio mcp single-op-call <tool> \'<json>\'` is equivalent and useful when you need to make the MCP boundary obvious. Use `webstudio mcp run \'[{"tool":"components.find","input":{"brief":"button"}}]\'` for multiple calls in one shared CLI session. Use a normal JSON file path for large batches. Use long-running `webstudio mcp` only when your environment is a real MCP client. Do not manually send raw JSON-RPC to `webstudio mcp` from a shell or PTY.\n3. Read MCP `meta.index`, for example `webstudio meta.index`.\n4. Use focused MCP calls with concrete JSON: `webstudio meta.guide \'{"brief":"Create a design system page using every component"}\'`, `webstudio meta.get-more-tools \'{"tools":["insert-fragment"]}\'`, `webstudio components.list \'{"source":"all"}\'`, `webstudio components.coverage-plan`, `webstudio components.search \'{"brief":"radix select"}\'`, `webstudio components.get \'{"component":"@webstudio-is/sdk-components-react-radix:Select"}\'`, `webstudio templates.list`, and `webstudio templates.get \'{"component":"@webstudio-is/sdk-components-react-radix:Select"}\'`.\n5. Read overview resources `webstudio://project/tools-overview` or `webstudio://project/components-overview` when useful. Read full resources `webstudio://project/tools` or `webstudio://project/components` only when focused tools are insufficient.\n6. Pick focused MCP read tool.\n7. Pick semantic MCP write tool.\n\nUse `webstudio schema mcp` for a compact MCP tool overview. Add `--verbose` only when exact input schemas for all tools are truly needed; otherwise prefer focused `meta.get-more-tools` and `components.*` calls.\n\nRun these commands from the linked project root. Use the MCP startup status line\'s absolute root for local files; write temporary scripts and artifacts under `<project root>/.temp`, not under a parent workspace.\n\nMonorepo quick path for a simple styled section:\n\n```sh\nnode packages/cli/local.js mcp single-op-call meta.index\nnode packages/cli/local.js mcp single-op-call m Line truncated
'# Webstudio CLI Manual for LLMs\n\nUse this order. Stop only when a command returns ok:false.\n\nIf you are inside the Webstudio monorepo, the first command discovery should use\nthe local CLI exactly as `node packages/cli/local.js ...` from the repo root. Do\nnot use `packages/cli/bin.js` for local source-tree work; it is the packaged\nbuild entry and may use stale built output. Do not use `pnpm exec webstudio`,\n`pnpm --filter webstudio exec webstudio`, or a global `webstudio`: they can\nresolve an older binary.\n\nFor delegated design-system or “use every component” tasks, skip the generic warm-up sequence and start with exactly one MCP command: `webstudio workflow.next \'{"goal":"design-system-page"}\'`. Report that returned checkpoint to the parent/user and stop until continued.\n\n## Use MCP locally or optionally connect a client\n\nDo not install, register, or connect an MCP server merely because the user asks\nyou to edit a Webstudio project. If Webstudio MCP tools are already available,\nuse them. If you have shell access, use the local CLI shortcuts such as\n`webstudio meta.index` and `webstudio list-pages`; they expose the same project\noperations without changing client configuration or restarting the app.\n\nOnly when the user explicitly asks for persistent native MCP integration, run\nthe command for their client:\n\n- Claude Code: `webstudio connect claude`\n- Codex: `webstudio connect codex`\n- Cursor: `webstudio connect cursor`\n- VS Code or GitHub Copilot: `webstudio connect vscode`\n\nRun project operations from the linked project root. If the folder is not\nlinked, ask for an editable Builder share link and run\n`webstudio init --link <share-link> --json`. You can then use local CLI\nshortcuts immediately. Do not run `webstudio sync`, `webstudio connect`, or\nrestart the app unless the user specifically wants native MCP registration:\nMCP reads and edits the latest editable Builder build directly, including for\nprojects that have never been published. Treat the share link as a credential\nand do not include it in committed files, logs, screenshots, or issue reports.\n\nThe optional `connect` command verifies project access before changing client configuration. For\nClaude Code, Cursor, and VS Code it safely merges the `webstudio` server into\nthe client\'s project configuration. For Codex it runs both `codex mcp add` and\n`codex mcp get webstudio`; do not repeat those commands separately. Follow the\nreload, restart, or approval instruction printed by `connect`, then verify the\nloaded MCP connection by asking the client to use Webstudio MCP and list the\nproject pages. Use `--print` only to inspect the generated setup without\nchanging configuration or requiring project access.\n\n## Always\n\n1. webstudio permissions --json\n2. For bounded shell workflows, call MCP tools directly through the CLI shortcut, for example `webstudio meta.index` or `webstudio insert-fragment \'<json>\' --dry-run`. The explicit form `webstudio mcp single-op-call <tool> \'<json>\'` is equivalent and useful when you need to make the MCP boundary obvious. Use `webstudio mcp run \'[{"tool":"components.find","input":{"brief":"button"}}]\'` for multiple calls in one shared CLI session. Use a normal JSON file path for large batches. Use long-running `webstudio mcp` only when your environment is a real MCP client. Do not manually send raw JSON-RPC to `webstudio mcp` from a shell or PTY.\n3. Read MCP `meta.index`, for example `webstudio meta.index`.\n4. Use focused MCP calls with concrete JSON: `webstudio meta.guide \'{"brief":"Create a design system page using every component"}\'`, `webstudio meta.get-more-tools \'{"tools":["insert-fragment"]}\'`, `webstudio components.list \'{"source":"all"}\'`, `webstudio components.coverage-plan`, `webstudio components.search \'{"brief":"radix select"}\'`, `webstudio components.get \'{"component":"@webstudio-is/sdk-components-react-radix:Select"}\'`, `webstudio templates.list`, and `webstudio templates.get \'{"component":"@webstudio-is/sdk-components-react-radix:Select"}\'`.\n5. Read overview resources `webstudio://project/tools-overview` or `webstudio://project/components-overview` when useful. Read full resources `webstudio://project/tools` or `webstudio://project/components` only when focused tools are insufficient.\n6. Pick focused MCP read tool.\n7. Pick semantic MCP write tool.\n\nUse `webstudio schema mcp` for a compact MCP tool overview. Add `--verbose` only when exact input schemas for all tools are truly needed; otherwise prefer focused `meta.get-more-tools` and `components.*` calls.\n\nRun these commands from the linked project root. Use the MCP startup status line\'s absolute root for local files; write temporary scripts and artifacts under `<project root>/.temp`, not under a parent workspace.\n\nMonorepo quick path for a simple styled section:\n\n```sh\nnode packages/cli/local.js mcp single-op-call meta.index\nnode packages/cli/local.js mcp single-op-call m Line truncated
"manual-mcp":
'# Webstudio MCP Manual\n\n`webstudio mcp` starts a stdio MCP server for real MCP clients. Shell users can call MCP tools with the shortcut form `webstudio <tool> \'<json>\'`, for example `webstudio meta.index` or `webstudio insert-fragment \'<json>\' --dry-run`. `webstudio mcp single-op-call` is the explicit equivalent and prints the structured JSON result. `webstudio mcp run` runs multiple MCP tool calls from inline JSON or a normal JSON file in one shared CLI session. Do not manually type or pipe raw JSON-RPC frames into `webstudio mcp` from an interactive shell or PTY.\n\n## Startup\n\nIf you are already working with a shell-capable agent, it can use the local CLI\ndirectly. Native MCP client registration is optional. Give the editable Builder\nshare link only when the trusted agent asks for it. Treat the share link as a\ncredential: do not include it in committed files, screenshots, logs, or issue\nreports.\n\n1. Configure a project with `webstudio init --link <api-share-link> --json`.\n2. Check capabilities with `webstudio permissions --json`.\n3. Use shortcut calls such as `webstudio meta.index` and `webstudio insert-fragment \'<json>\' --dry-run` for individual MCP tool calls. Use the explicit equivalent `webstudio mcp single-op-call <tool> \'<json>\'` when you need to force the MCP path, or `webstudio mcp run \'[{"tool":"components.find","input":{"brief":"button"}}]\'` for bounded multi-call workflows. Use `webstudio mcp run .temp/mcp-calls.json` for large batches.\n4. Start discovery with `meta.index`, then call focused tools with concrete JSON, for example `webstudio mcp single-op-call meta.guide \'{"brief":"Create a design system page using every component"}\'`.\n\nDo not run `webstudio sync`, install an MCP server, change client configuration,\nor restart the app for this local CLI workflow.\n\nWhen the user explicitly wants persistent native MCP integration, run\n`webstudio connect claude`, `webstudio connect codex`, `webstudio connect\ncursor`, or `webstudio connect vscode`. This optional command changes client\nconfiguration, so follow its client-specific reload or restart instruction.\nUse `--print` to inspect the generated setup without changing configuration or\nrequiring project access. For Codex, `connect` registers and verifies the server\nthrough the Codex CLI. Before changing client configuration, `connect` verifies\nthat the saved project endpoint is reachable and its credential is accepted.\n\nStart MCP from the linked Webstudio project root. The lifecycle status line prints that absolute root; create local scripts, screenshots, and temporary artifacts under that root, for example `<project root>/.temp/script.mjs`. If the shell starts in a parent workspace, `cd` into the project root first or use absolute paths.\n\nWhen developing inside the Webstudio monorepo, start the local CLI exactly as `node packages/cli/local.js mcp` from the repo root. Do not use `pnpm exec webstudio`, `pnpm --filter webstudio exec webstudio`, or a global `webstudio`: they can resolve an older binary.\n\nWhile the server is running, stdout is reserved for MCP JSON-RPC messages. Do not print human text from the server process. The server advertises MCP `logging` capability and emits sparse `notifications/message` logs for ready state and tool lifecycle checkpoints such as `tool preview.start started`, `tool preview.start still running after 10000ms`, and `tool preview.start succeeded in 1234ms`; stderr also mirrors these sparse lifecycle fallback lines prefixed with `[webstudio mcp]`.\n\n## One-Shot Tool Calls\n\nUse the shortcut `webstudio <tool> \'<json>\'` when you are operating from a shell and need one MCP tool result. The explicit form `webstudio mcp single-op-call <tool> \'<json>\'` is equivalent and avoids writing temporary Node.js stdio client scripts.\n\nExamples:\n\n```sh\nwebstudio mcp single-op-call meta.index\nwebstudio mcp single-op-call meta.guide \'{"brief":"Create a design system page using every component"}\'\nwebstudio mcp single-op-call meta.get-more-tools \'{"tools":["insert-fragment"]}\'\nwebstudio mcp single-op-call components.list \'{"source":"all"}\'\nwebstudio mcp single-op-call components.coverage-plan\nwebstudio mcp single-op-call components.search \'{"brief":"radix select"}\'\nwebstudio mcp single-op-call components.get \'{"component":"@webstudio-is/sdk-components-react-radix:Select"}\'\nwebstudio mcp single-op-call templates.list\nwebstudio mcp single-op-call templates.get \'{"component":"@webstudio-is/sdk-components-react-radix:Select"}\'\nwebstudio mcp single-op-call insert-fragment --input-file .temp/insert-fragment.json\n```\n\nShortcut equivalents:\n\n```sh\nwebstudio meta.index\nwebstudio meta.guide \'{"brief":"Create a design system page using every component"}\'\nwebstudio meta.get-more-tools \'{"tools":["insert-fragment"]}\'\nwebstudio components.list \'{"source":"all"}\'\nwebstudio components.coverage-plan\nwebstudio components.search \'{"brief":"radix select"}\'Line truncated
'# Webstudio MCP Manual\n\n`webstudio mcp` starts a stdio MCP server for real MCP clients. Shell users can call MCP tools with the shortcut form `webstudio <tool> \'<json>\'`, for example `webstudio meta.index` or `webstudio insert-fragment \'<json>\' --dry-run`. `webstudio mcp single-op-call` is the explicit equivalent and prints the structured JSON result. `webstudio mcp run` runs multiple MCP tool calls from inline JSON or a normal JSON file in one shared CLI session. Do not manually type or pipe raw JSON-RPC frames into `webstudio mcp` from an interactive shell or PTY.\n\n## Startup\n\nIf you are already working with a shell-capable agent, it can use the local CLI\ndirectly. Native MCP client registration is optional. Give the editable Builder\nshare link only when the trusted agent asks for it. Treat the share link as a\ncredential: do not include it in committed files, screenshots, logs, or issue\nreports.\n\n1. Configure a project with `webstudio init --link <api-share-link> --json`.\n2. Check capabilities with `webstudio permissions --json`.\n3. Use shortcut calls such as `webstudio meta.index` and `webstudio insert-fragment \'<json>\' --dry-run` for individual MCP tool calls. Use the explicit equivalent `webstudio mcp single-op-call <tool> \'<json>\'` when you need to force the MCP path, or `webstudio mcp run \'[{"tool":"components.find","input":{"brief":"button"}}]\'` for bounded multi-call workflows. Use `webstudio mcp run .temp/mcp-calls.json` for large batches.\n4. Start discovery with `meta.index`, then call focused tools with concrete JSON, for example `webstudio mcp single-op-call meta.guide \'{"brief":"Create a design system page using every component"}\'`.\n\nDo not run `webstudio sync`, install an MCP server, change client configuration,\nor restart the app for this local CLI workflow.\n\nWhen the user explicitly wants persistent native MCP integration, run\n`webstudio connect claude`, `webstudio connect codex`, `webstudio connect\ncursor`, or `webstudio connect vscode`. This optional command changes client\nconfiguration, so follow its client-specific reload or restart instruction.\nUse `--print` to inspect the generated setup without changing configuration or\nrequiring project access. For Codex, `connect` registers and verifies the server\nthrough the Codex CLI. Before changing client configuration, `connect` verifies\nthat the saved project endpoint is reachable and its credential is accepted.\n\nStart MCP from the linked Webstudio project root. The lifecycle status line prints that absolute root; create local scripts, screenshots, and temporary artifacts under that root, for example `<project root>/.temp/script.mjs`. If the shell starts in a parent workspace, `cd` into the project root first or use absolute paths.\n\nWhen developing inside the Webstudio monorepo, start the local CLI exactly as `node packages/cli/local.js mcp` from the repo root. Do not use `pnpm exec webstudio`, `pnpm --filter webstudio exec webstudio`, or a global `webstudio`: they can resolve an older binary.\n\nWhile the server is running, stdout is reserved for MCP JSON-RPC messages. Do not print human text from the server process. The server advertises MCP `logging` capability and emits sparse `notifications/message` logs for ready state and tool lifecycle checkpoints such as `tool preview.start started`, `tool preview.start still running after 10000ms`, and `tool preview.start succeeded in 1234ms`; stderr also mirrors these sparse lifecycle fallback lines prefixed with `[webstudio mcp]`.\n\n## One-Shot Tool Calls\n\nUse the shortcut `webstudio <tool> \'<json>\'` when you are operating from a shell and need one MCP tool result. The explicit form `webstudio mcp single-op-call <tool> \'<json>\'` is equivalent and avoids writing temporary Node.js stdio client scripts.\n\nExamples:\n\n```sh\nwebstudio mcp single-op-call meta.index\nwebstudio mcp single-op-call meta.guide \'{"brief":"Create a design system page using every component"}\'\nwebstudio mcp single-op-call meta.get-more-tools \'{"tools":["insert-fragment"]}\'\nwebstudio mcp single-op-call components.list \'{"source":"all"}\'\nwebstudio mcp single-op-call components.coverage-plan\nwebstudio mcp single-op-call components.search \'{"brief":"radix select"}\'\nwebstudio mcp single-op-call components.get \'{"component":"@webstudio-is/sdk-components-react-radix:Select"}\'\nwebstudio mcp single-op-call templates.list\nwebstudio mcp single-op-call templates.get \'{"component":"@webstudio-is/sdk-components-react-radix:Select"}\'\nwebstudio mcp single-op-call insert-fragment --input-file .temp/insert-fragment.json\n```\n\nShortcut equivalents:\n\n```sh\nwebstudio meta.index\nwebstudio meta.guide \'{"brief":"Create a design system page using every component"}\'\nwebstudio meta.get-more-tools \'{"tools":["insert-fragment"]}\'\nwebstudio components.list \'{"source":"all"}\'\nwebstudio components.coverage-plan\nwebstudio components.search \'{"brief":"radix select"}\'Line truncated
"mcp-startup-epilogue":
'If you are inside the Webstudio monorepo, use the local CLI exactly as `node packages/cli/local.js ...` as your first command path. Do not use `packages/cli/bin.js` for local source-tree work; it is the packaged build entry and may use stale built output.\n\nPlain `webstudio mcp` starts the stdio MCP server for real MCP clients. Do not manually type or pipe raw JSON-RPC frames into it from an interactive shell or PTY. From a shell, use shortcut calls such as `webstudio meta.index` and `webstudio insert-fragment \'<json>\' --dry-run` for one bounded tool call. The explicit equivalent is `webstudio mcp single-op-call <tool> \'<json>\'`. Use `webstudio mcp run \'[{"tool":"components.find","input":{"brief":"button"}}]\'` for small multi-call batches in one shared CLI session. For large batches, pass a normal JSON file path such as `.temp/mcp-calls.json`. Do not use shell process substitution like `<(...)`; use inline JSON or a real file.\n\nPut each local CLI call in its own shell command; do not chain helper commands with `&&`, `;`, command substitution, or shell wrappers around the CLI when reporting a CLI step. Do not use `pnpm exec webstudio`, `pnpm --filter webstudio exec webstudio`, or a global `webstudio`; those can resolve an older binary. For example:\n\n```sh\nnode packages/cli/local.js mcp single-op-call meta.index\nnode packages/cli/local.js mcp single-op-call meta.get-more-tools \'{"tools":["insert-fragment"]}\'\nnode packages/cli/local.js mcp single-op-call insert-fragment --input-file .temp/insert-fragment.json --dry-run\n```\n\nSave the input as `.temp/insert-fragment.json`; use single quotes for JSX attributes so the JSON needs no backslash escaping:\n\n```json\n{\n "parentInstanceId": "parent-id",\n "fragment": "<section ws:style={css`padding: 32px; display: grid; gap: 12px;`}><h2>Launch Kit</h2><p>A focused section created with Webstudio JSX.</p><button>Get started</button></section>"\n}\n```\n\nThe shorter local shortcut form is preferred for simple shell steps:\n\n```sh\nnode packages/cli/local.js meta.index\nnode packages/cli/local.js meta.get-more-tools \'{"tools":["insert-fragment"]}\'\nnode packages/cli/local.js insert-fragment --input-file .temp/insert-fragment.json --dry-run\n```\n\nFor simple authored/styled sections, run the three commands above. Do not grep source files, dump full MCP resources, or write parser scripts first. Use `list-pages`, `get-page-by-path`, or `list-instances` only when you still need the target `parentInstanceId`.\n\nWhen building for a Content-mode editor, use a Content Block (`ws:block`) around every region that editor must change. Content-mode text and supported props are editable only in Content Block descendants; content outside is read-only. Keep reusable insertable source options in exactly one direct `ws:block-template` child. A missing or second template container makes the block invalid. Templates themselves are protected; an editor\'s inserted copy becomes editable Content Block body content. Verify this structure before handoff.\n\nFor an MDX-backed Content Block, use the dedicated content-source tools instead of generic prop mutations: connect, switch, inspect, edit, update frontmatter, reload, or disconnect the source. Confirm before replacing existing Body content. Prefer Markdown for standard document content; it automatically uses unique matching semantic templates. Use lowercase JSX such as `<section>` or `<svg>` for HTML or SVG that Markdown cannot express. Capitalized JSX resolves a unique stable template **Name** or a built-in MDX adapter. Add custom components to this Content Block\'s Templates before referencing them in MDX. The display label is independent. JSX attributes accept quoted values and bare booleans; expressions such as `{false}` are unsupported. Legacy `ws.element` and `ws:name` forms are compatibility input only. Component namespaces such as `$.*`, `radix.*`, and `animation.*` are unsupported; use direct component identifiers. Matching explicit children overlay designed descendants and keep template styles. A mismatched child structure replaces defaults, an explicit empty pair clears defaults, and a self-closing reference keeps them. Editing inherited default content writes it back as explicit JSX children. Template resolution is live when matching templates are added later. Preserve invalid source and unresolved names, inspect all diagnostics, and reload before retrying a revision conflict. A frontmatter update replaces the complete property map; preserve fields the user did not ask to remove. Store frontmatter images as exact `$ref` objects; bind Image sources to `.src` and alt properties to the Asset `.description`. Only exact direct frontmatter bindings may use `mode:"readwrite"`. After a template rename or deletion, use `migrate-content-block-template-references` to preview and confirm custom-template JSX and legacy changes across selected MDX files. A confirmed removal unwraps paired references and preservesLine truncated
'If you are inside the Webstudio monorepo, use the local CLI exactly as `node packages/cli/local.js ...` as your first command path. Do not use `packages/cli/bin.js` for local source-tree work; it is the packaged build entry and may use stale built output.\n\nPlain `webstudio mcp` starts the stdio MCP server for real MCP clients. Do not manually type or pipe raw JSON-RPC frames into it from an interactive shell or PTY. From a shell, use shortcut calls such as `webstudio meta.index` and `webstudio insert-fragment \'<json>\' --dry-run` for one bounded tool call. The explicit equivalent is `webstudio mcp single-op-call <tool> \'<json>\'`. Use `webstudio mcp run \'[{"tool":"components.find","input":{"brief":"button"}}]\'` for small multi-call batches in one shared CLI session. For large batches, pass a normal JSON file path such as `.temp/mcp-calls.json`. Do not use shell process substitution like `<(...)`; use inline JSON or a real file.\n\nPut each local CLI call in its own shell command; do not chain helper commands with `&&`, `;`, command substitution, or shell wrappers around the CLI when reporting a CLI step. Do not use `pnpm exec webstudio`, `pnpm --filter webstudio exec webstudio`, or a global `webstudio`; those can resolve an older binary. For example:\n\n```sh\nnode packages/cli/local.js mcp single-op-call meta.index\nnode packages/cli/local.js mcp single-op-call meta.get-more-tools \'{"tools":["insert-fragment"]}\'\nnode packages/cli/local.js mcp single-op-call insert-fragment --input-file .temp/insert-fragment.json --dry-run\n```\n\nSave the input as `.temp/insert-fragment.json`; use single quotes for JSX attributes so the JSON needs no backslash escaping:\n\n```json\n{\n "parentInstanceId": "parent-id",\n "fragment": "<section ws:style={css`padding: 32px; display: grid; gap: 12px;`}><h2>Launch Kit</h2><p>A focused section created with Webstudio JSX.</p><button>Get started</button></section>"\n}\n```\n\nThe shorter local shortcut form is preferred for simple shell steps:\n\n```sh\nnode packages/cli/local.js meta.index\nnode packages/cli/local.js meta.get-more-tools \'{"tools":["insert-fragment"]}\'\nnode packages/cli/local.js insert-fragment --input-file .temp/insert-fragment.json --dry-run\n```\n\nFor simple authored/styled sections, run the three commands above. Do not grep source files, dump full MCP resources, or write parser scripts first. Use `list-pages`, `get-page-by-path`, or `list-instances` only when you still need the target `parentInstanceId`.\n\nWhen building for a Content-mode editor, use a Content Block (`ws:block`) around every region that editor must change. Content-mode text and supported props are editable only in Content Block descendants; content outside is read-only. Keep reusable insertable source options in exactly one direct `ws:block-template` child. A missing or second template container makes the block invalid. Templates themselves are protected; an editor\'s inserted copy becomes editable Content Block body content. Verify this structure before handoff.\n\nFor an MDX-backed Content Block, use the dedicated content-source tools instead of generic prop mutations: connect, switch, inspect, edit, update frontmatter, reload, or disconnect the source. Confirm before replacing existing Body content. Prefer Markdown for standard document content; it automatically uses unique matching semantic templates. Use lowercase JSX such as `<section>` or `<svg>` for HTML or SVG that Markdown cannot express. Capitalized JSX resolves a unique stable template **Name** or a built-in MDX adapter. Add custom components to this Content Block\'s Templates before referencing them in MDX. The display label is independent. JSX attributes accept quoted values and bare booleans; expressions such as `{false}` are unsupported. Legacy `ws.element` and `ws:name` forms are compatibility input only. Component namespaces such as `$.*`, `radix.*`, and `animation.*` are unsupported; use direct component identifiers. Matching explicit children overlay designed descendants and keep template styles. A mismatched child structure replaces defaults, an explicit empty pair clears defaults, and a self-closing reference keeps them. Editing inherited default content writes it back as explicit JSX children. Template resolution is live when matching templates are added later. Preserve invalid source and unresolved names, inspect all diagnostics, and reload before retrying a revision conflict. A frontmatter update replaces the complete property map; preserve fields the user did not ask to remove. Store frontmatter images as exact `$ref` objects; bind editable Image sources to `.src` with explicit `binding.mode:"readwrite"` and alt properties to the Asset `.description` with `mode:"read"`. Omitting the source mode leaves the image visible but not replaceable in Content mode. Only exact direct frontmatter bindings may use `mode:"readwrite"`. After a template rename or deletion, use `migrate-content-block-template-refe Line truncated
"mcp-vision":
'# MCP Vision Verification\n\n## Generated App Dependency Notes\n\n- `preview.start` and `webstudio preview` install generated app dependencies under `.webstudio/preview` and reuse them across regenerations.\n- Session previews download missing project assets into `.webstudio/assets`. If `PREVIEW_ASSET_DOWNLOAD_FAILED` occurs, restore network and project asset access, then retry `preview.start`.\n- When launcher metadata is available, dependency installation reuses a supported npm or pnpm launcher. Without launcher metadata, it defaults to npm.\n- When npm is selected, dependency installation honors `npm_config_cache`. If it is unset, preview uses the writable `.webstudio/preview/.npm-cache` directory instead of the user\'s default npm cache.\n- For npm cache permission errors, unset `npm_config_cache` to use the preview-local cache, then retry. No cache deletion is required.\n- Do not add generated-preview dependencies to the repository root `package.json` or `pnpm-lock.yaml`.\n- If dependency installation fails, the error includes the selected package-manager path and sanitized diagnostics. Check that path and the network configuration, then reinstall or update the Webstudio CLI if the problem persists.\n\n## Visual Verification Rule\n\nAsk the user whether they want visual verification before starting it, unless the user explicitly requested screenshots, visual verification, or a rendered audit. Never start `preview.start`, `screenshot`, `screenshot.diff`, `vision.install-ocr`, or a rendered audit automatically. If the user does not opt in, use focused non-visual assertions and report that vision was not run. After the user opts in, use `preview.start` and `screenshot({ path })` so vision can inspect the current MCP session and verify that generated project files are current. Iterative preview is the default: it keeps one generated-site server and browser alive, regenerates changed files, and performs an ordinary page reload without Vite HMR. Use `mode: "production"` only for release-like verification; rendered audit selects it automatically. `preview.start` is long-lived and cannot be used through one-shot `mcp single-op-call`; from a shell, use `webstudio mcp run` for preview.start/screenshot/preview.stop in one shared process, or use a long-running MCP server. When a baseline exists, use screenshot.diff to get pixel regions, OCR text changes, and diff PNG artifacts.\n\nAn authenticated project share URL is used with `webstudio init --link`; it is\nnot a generated-site preview URL. Project screenshots and rendered audits use\nthe generated local preview owned by the current CLI/MCP process. Do not pass a\nBuilder/share URL to `screenshot`, even without query parameters. Use `path`\nafter starting preview, or use `baseUrl` only for an intentional generated site\nthat is already running. Path captures verify the generated-site root marker\nand fail instead of returning a screenshot of Builder chrome.\n\n## Vision Verification Loop\n\n- Ask the user whether they want visual verification unless they explicitly requested it. Stop before calling preview, capture, comparison, OCR, or rendered-audit tools until the user opts in.\n- Make focused page/content/style changes with semantic MCP tools.\n- Call preview.start once to keep the iterative generated site running. In shell-driven workflows, run preview.start, screenshot, and preview.stop inside one `webstudio mcp run` call so they share the same preview owner.\n- Read `preview.status.stale` before relying on generated output. When present, `renderedProjectVersion` identifies the last project version materialized into the preview; a stale preview refreshes automatically on the next managed screenshot or `preview.start` call.\n- {{dependency-notes}}\n- After MCP mutations, path-based screenshots regenerate the current session in place, wait for its exact project version, and normally reload the route. The server and browser remain alive. From one-shot shell calls or another process, pass `baseUrl` with `path` to capture an already-running generated site without starting it. Use preview.stop only in the same long-running MCP server or `webstudio mcp run` process that started preview; a separate one-shot `single-op-call` process does not own another process\'s preview controller.\n- For multi-page work, capture each changed page by path through the same preview server, for example screenshot({ path: "/" }), screenshot({ path: "/pricing" }), and screenshot({ path: "/about" }). The screenshot tool navigates directly to the requested route; no browser click navigation is required.\n- For responsive work, call list-breakpoints first, then capture screenshots at viewport widths based on the Builder breakpoints plus a narrow mobile and desktop width.\n- Call screenshot with { path: "/" } or the changed page path and viewport such as { width: 375, height: 812 } and { width: 1440, height: 900 }. For an existing preview in another process, call screenshot with { baLine truncated
} as const;
+20 -2
View File
@@ -485,8 +485,8 @@ Notes:
- When a template is renamed or deleted, use `migrate-content-block-template-references` to update a selected set of affected MDX files. The first call returns a plan. Report its changed-file, update, omission, and diagnostic counts, then repeat the exact request with its `confirmationToken` only after approval. Renames and removals update named JSX and legacy `ws:name` references, including names such as `Image` and `CodeText` when they identify templates. Rename targets must be valid PascalCase JSX identifiers. Removing a paired reference unwraps and preserves its authored children; removing a self-closing reference removes the node because it has no authored children. Invalid files remain unchanged and are reported in diagnostics.
- `edit-content-block-source` replaces the complete MDX source. Preserve frontmatter and unrelated source when making a bounded edit.
- `update-content-block-frontmatter` replaces the complete frontmatter mapping. Inspect the current source first and include every property that must remain.
- Store frontmatter images as exact `$ref` objects. Bind an Image source to the resolved `.src` field and its alt property to `.description` so the Asset description supplies alternative text.
- Use `update-content-block-frontmatter` for MCP frontmatter edits. MDX-rendered elements are not persistent instance targets for generic `bind-props` or `update-text` calls. Preserve existing `mode:"readwrite"` bindings when encountered; they are valid only for exact direct paths into the connected document's frontmatter. Direct bindings through a loaded Markdown or MDX `$ref` ending in `#frontmatter` save to the referenced file, with its write permissions enforced. Shared-record edits affect every document using that record. Computed expressions, JSON/body references, and resolved image metadata remain read-only.
- Store frontmatter images as exact `$ref` objects. Bind an editable Image source to the resolved `.src` with explicit `binding.mode:"readwrite"`; use `mode:"read"` for its alt binding to `.description`. Omitting the source mode leaves the image visible but not replaceable in Content mode.
- Use `update-content-block-frontmatter` for MCP frontmatter edits. MDX-rendered elements are not persistent instance targets for generic `bind-props` or `update-text` calls. Preserve existing `mode:"readwrite"` bindings when encountered; they are valid only for exact direct paths into the connected document's frontmatter. Direct bindings through a loaded Markdown or MDX `$ref` ending in `#frontmatter` save to the referenced file, with its write permissions enforced. Shared-record edits affect every document using that record. Computed expressions and JSON/body references remain read-only. Image replacement is supported: a direct Image source binding with `mode:"readwrite"` lets the picker replace the frontmatter `$ref`, while shared Asset metadata is edited in Asset settings.
- Inspect every returned diagnostic. Invalid MDX is saved rather than silently repaired; preserve the source, report the source range, and fix only the requested or invalid part.
- If an edit in a long-lived MCP session reports a conflict after another client saved the Asset, call `reload-content-block-source`, inspect the latest source, reapply the requested change, and retry. One-shot CLI calls refresh before each operation and normally cannot reproduce a stale session. Never overwrite the newer revision blindly.
@@ -516,6 +516,24 @@ Notes:
- Before handoff, inventory every article-owned field, including header text, author details, dates, reading time, categories, hero and inline image sources, alternative text, captions, links, and custom-component content. For each field, inspect its binding and source, edit it through the Content-mode UI, verify the saved MDX or referenced file, reload, and restore the test value. Record passed, failed, or not tested for each field. A correct preview, a successful MCP write, and one representative text edit do not prove the whole article is editable. Do not claim completion while required fields fail or remain untested.
- Bind the Image source directly to `document.frontmatter.featureImage.src` with `binding.mode:"readwrite"` using `bind-props`. Content mode's **Choose source** replaces the article's frontmatter image `$ref`; the resolved URL stays read-only. Verify selection, the saved reference, and reload instead of treating a missing write mode as a platform limitation. For alternative text bound to `.description`, use **Choose source → asset actions → Settings → Description** to edit shared Asset metadata. This affects every use of the Asset and is separate from replacing an article's image.
## Make an article image replaceable in Content mode
Use this for a persistent designed Image inside a connected Content Block,
with `featureImage: { $ref: "./images/hero.png" }` in its MDX frontmatter.
Read the instance ID and document variable name before adapting the example.
Commands:
- MCP tool: bind-props {"bindings":[{"instanceId":"<imageInstanceId>","name":"src","binding":{"type":"expression","value":"document.frontmatter.featureImage.src","mode":"readwrite"}},{"instanceId":"<imageInstanceId>","name":"alt","binding":{"type":"expression","value":"document.frontmatter.featureImage.description","mode":"read"}}]}
Notes:
- The source mode must be explicit: the default `read` mode displays the image but prevents Content-mode replacement. Do not bind to query-result properties or add a fallback expression.
- **Choose source** replaces the article's `featureImage.$ref`; the disabled resolved-URL input is expected. Do not store a resolved URL string or replace the shared Asset itself.
- Shared alternative text is a separate action: **Choose source → asset actions → Settings → Description**. Its read-only binding does not require the image source binding to be read-only.
- If the picker is missing or disabled, inspect the source mode, document scope, loaded reference, and permissions before claiming a product limitation.
- Verify through Content mode with an approved temporary replacement. Check the saved `$ref`, unchanged unrelated MDX and original shared Asset, reload persistence, and restoration. If that test is not authorized, report it as not tested, not passed.
## Move elements
Commands:
+2 -2
View File
@@ -92,9 +92,9 @@ When the task says another user will edit a page in Content mode, use a Content
When the Content Block body must be stored in an `.mdx` Asset, use the dedicated `connect-content-block-source`, `switch-content-block-source`, `inspect-content-block-source`, `edit-content-block-source`, `update-content-block-frontmatter`, `reload-content-block-source`, and `disconnect-content-block-source` tools. Do not manipulate its `src` with generic prop tools. Connecting replaces existing Body content, so report `requiresConfirmation:true` and retry with `confirmReplacement:true` only after user approval. Prefer Markdown for standard document content; it automatically uses unique matching semantic templates. Use lowercase JSX such as `<section>` or `<svg>` for HTML or SVG that Markdown cannot express. Capitalized JSX resolves a unique stable template **Name** or a built-in MDX adapter. Add custom components to this Content Block's Templates before referencing them in MDX. The display label is independent. JSX attributes accept quoted values and bare booleans; expressions such as `{false}` are unsupported. Legacy `ws.element` and `ws:name` forms are compatibility input only. Component namespaces such as `$.*`, `radix.*`, and `animation.*` are unsupported; use direct component identifiers. Matching explicit children overlay designed descendants and keep their template styles. A mismatched child structure replaces defaults, while an explicit empty pair clears defaults and a self-closing reference keeps them. Editing inherited default content writes it back as explicit JSX children. Template resolution is live, including when a matching template is added after the MDX element. Preserve invalid MDX and unresolved template names, inspect all source-located diagnostics, and resolve revision conflicts by reloading before reapplying the change. After a template rename or deletion, use `migrate-content-block-template-references` to preview and confirm custom-template JSX and legacy updates across selected MDX files. A confirmed removal unwraps paired references and preserves their authored children; a self-closing reference disappears because it has none.
Frontmatter is part of the same MDX source. `update-content-block-frontmatter` receives the complete replacement property map, so inspect and preserve properties the user did not ask to remove. Store frontmatter images as exact `$ref` objects, bind Image sources to their resolved `.src`, and bind alt properties to their Asset `.description`. Use `update-content-block-frontmatter` for MCP frontmatter edits; MDX-rendered elements are not persistent targets for generic prop or text mutations. Preserve existing `mode:"readwrite"` bindings, which are valid only for exact direct frontmatter paths. Direct bindings through a loaded Markdown or MDX `$ref` ending in `#frontmatter` save to the referenced file, with its write permissions enforced. Shared-record edits affect every document using that record. Computed expressions, JSON/body references, and resolved image metadata remain read-only. For an expression-bound source inside a Collection, pass the occurrence's scoped values and a distinct stable `renderScope`; for example, resolve `post.assetId` with `variables:{"post":{"assetId":"<mdxAssetId>"}}`.
Frontmatter is part of the same MDX source. `update-content-block-frontmatter` receives the complete replacement property map, so inspect and preserve properties the user did not ask to remove. Store frontmatter images as exact `$ref` objects. Bind editable Image sources to their resolved `.src` with explicit `binding.mode:"readwrite"`; omitting the mode leaves the image visible but not replaceable in Content mode. Bind alt properties to their Asset `.description` with `mode:"read"`. Use `update-content-block-frontmatter` for MCP frontmatter edits; MDX-rendered elements are not persistent targets for generic prop or text mutations. Preserve existing `mode:"readwrite"` bindings, which are valid only for exact direct frontmatter paths. Direct bindings through a loaded Markdown or MDX `$ref` ending in `#frontmatter` save to the referenced file, with its write permissions enforced. Shared-record edits affect every document using that record. Computed expressions and JSON/body references remain read-only. Image replacement is supported: a direct Image source binding with `mode:"readwrite"` lets the picker replace the frontmatter `$ref`, while shared Asset metadata is edited in Asset settings. For an expression-bound source inside a Collection, pass the occurrence's scoped values and a distinct stable `renderScope`; for example, resolve `post.assetId` with `variables:{"post":{"assetId":"<mdxAssetId>"}}`.
For an editable MDX article, use the resource to select the Content Block's source Asset (`post.data.id`), then bind article fields inside the block to its document parameter (`document.frontmatter.title`), not query-result properties. Inspect the actual document variable name first. Create writable bindings explicitly: `update-text` uses `expressionBindingMode:"readwrite"`; `bind-props` uses `binding.mode:"readwrite"`. These generic tools target persistent designed instances, such as a header outside the MDX body, not MDX-generated instances. The MDX body is editable through its source mapping; merely placing static or query-bound content inside the block does not make it editable. Use exact direct paths; property access is already safe. Direct bindings through a loaded Markdown or MDX `$ref` ending in `#frontmatter` save to the referenced file, with its write permissions enforced. Shared-record edits affect every document using that record. Computed expressions, JSON/body references, and resolved image metadata remain read-only. Follow the complete article editability checklist below before handoff.
For an editable MDX article, use the resource to select the Content Block's source Asset (`post.data.id`), then bind article fields inside the block to its document parameter (`document.frontmatter.title`), not query-result properties. Inspect the actual document variable name first. Create writable bindings explicitly: `update-text` uses `expressionBindingMode:"readwrite"`; `bind-props` uses `binding.mode:"readwrite"`. These generic tools target persistent designed instances, such as a header outside the MDX body, not MDX-generated instances. The MDX body is editable through its source mapping; merely placing static or query-bound content inside the block does not make it editable. Use exact direct paths; property access is already safe. Direct bindings through a loaded Markdown or MDX `$ref` ending in `#frontmatter` save to the referenced file, with its write permissions enforced. Shared-record edits affect every document using that record. Computed expressions and JSON/body references remain read-only. Image replacement is supported: a direct Image source binding with `mode:"readwrite"` lets the picker replace the frontmatter `$ref`, while shared Asset metadata is edited in Asset settings. Follow the complete article editability checklist below before handoff.
### Content Block completion checklist
+2 -2
View File
@@ -162,9 +162,9 @@ Use the dedicated connect, switch, inspect, edit, update-frontmatter, reload, an
`renderScope` is any non-empty stable identity for one rendered occurrence, such as `page:/articles/example`. It does not load that page, its route parameters, or its resource results. To connect a result-one Assets resource, run `preview-asset-query` with concrete values, keep the saved source expression such as `post.data.id`, and supply the previewed item for this occurrence with `variables:{"post":{"data":{"id":"<mdxAssetId>"}}}`. The operation validates that concrete Asset while persisting the dynamic expression.
A source edit replaces the complete MDX document. A frontmatter update replaces the complete frontmatter property map. Inspect the current source first and preserve everything the user did not ask to change. Store frontmatter images as exact `$ref` objects, bind Image sources to their resolved `.src`, and bind alt properties to their Asset `.description`. Use `update-content-block-frontmatter` for MCP frontmatter edits. MDX-rendered elements are not persistent instance targets for generic `bind-props` or `update-text` calls. Preserve existing `mode:"readwrite"` bindings when encountered; they are valid only for exact direct paths into the connected document's frontmatter. Direct bindings through a loaded Markdown or MDX `$ref` ending in `#frontmatter` save to the referenced file, with its write permissions enforced. Shared-record edits affect every document using that record. Computed expressions, JSON/body references, and resolved image metadata remain read-only.
A source edit replaces the complete MDX document. A frontmatter update replaces the complete frontmatter property map. Inspect the current source first and preserve everything the user did not ask to change. Store frontmatter images as exact `$ref` objects. Bind editable Image sources to their resolved `.src` with explicit `binding.mode:"readwrite"`; omitting the mode leaves the image visible but not replaceable in Content mode. Bind alt properties to their Asset `.description` with `mode:"read"`. Use `update-content-block-frontmatter` for MCP frontmatter edits. MDX-rendered elements are not persistent instance targets for generic `bind-props` or `update-text` calls. Preserve existing `mode:"readwrite"` bindings when encountered; they are valid only for exact direct paths into the connected document's frontmatter. Direct bindings through a loaded Markdown or MDX `$ref` ending in `#frontmatter` save to the referenced file, with its write permissions enforced. Shared-record edits affect every document using that record. Computed expressions and JSON/body references remain read-only. Image replacement is supported: a direct Image source binding with `mode:"readwrite"` lets the picker replace the frontmatter `$ref`, while shared Asset metadata is edited in Asset settings.
For an editable MDX article, use the resource to select the Content Block's source Asset (`post.data.id`), then bind article fields inside the block to its document parameter (`document.frontmatter.title`), not query-result properties. Inspect the actual document variable name first. Create writable bindings explicitly: `update-text` uses `expressionBindingMode:"readwrite"`; `bind-props` uses `binding.mode:"readwrite"`. These generic tools target persistent designed instances, such as a header outside the MDX body, not MDX-generated instances. The MDX body is editable through its source mapping; merely placing static or query-bound content inside the block does not make it editable. Use exact direct paths; property access is already safe. Direct bindings through a loaded Markdown or MDX `$ref` ending in `#frontmatter` save to the referenced file, with its write permissions enforced. Shared-record edits affect every document using that record. Computed expressions, JSON/body references, and resolved image metadata remain read-only. Follow the complete article editability checklist below before handoff.
For an editable MDX article, use the resource to select the Content Block's source Asset (`post.data.id`), then bind article fields inside the block to its document parameter (`document.frontmatter.title`), not query-result properties. Inspect the actual document variable name first. Create writable bindings explicitly: `update-text` uses `expressionBindingMode:"readwrite"`; `bind-props` uses `binding.mode:"readwrite"`. These generic tools target persistent designed instances, such as a header outside the MDX body, not MDX-generated instances. The MDX body is editable through its source mapping; merely placing static or query-bound content inside the block does not make it editable. Use exact direct paths; property access is already safe. Direct bindings through a loaded Markdown or MDX `$ref` ending in `#frontmatter` save to the referenced file, with its write permissions enforced. Shared-record edits affect every document using that record. Computed expressions and JSON/body references remain read-only. Image replacement is supported: a direct Image source binding with `mode:"readwrite"` lets the picker replace the frontmatter `$ref`, while shared Asset metadata is edited in Asset settings. Follow the complete article editability checklist below before handoff.
### Content Block completion checklist
@@ -31,9 +31,9 @@ For simple authored/styled sections, run the three commands above. Do not grep s
When building for a Content-mode editor, use a Content Block (`ws:block`) around every region that editor must change. Content-mode text and supported props are editable only in Content Block descendants; content outside is read-only. Keep reusable insertable source options in exactly one direct `ws:block-template` child. A missing or second template container makes the block invalid. Templates themselves are protected; an editor's inserted copy becomes editable Content Block body content. Verify this structure before handoff.
For an MDX-backed Content Block, use the dedicated content-source tools instead of generic prop mutations: connect, switch, inspect, edit, update frontmatter, reload, or disconnect the source. Confirm before replacing existing Body content. Prefer Markdown for standard document content; it automatically uses unique matching semantic templates. Use lowercase JSX such as `<section>` or `<svg>` for HTML or SVG that Markdown cannot express. Capitalized JSX resolves a unique stable template **Name** or a built-in MDX adapter. Add custom components to this Content Block's Templates before referencing them in MDX. The display label is independent. JSX attributes accept quoted values and bare booleans; expressions such as `{false}` are unsupported. Legacy `ws.element` and `ws:name` forms are compatibility input only. Component namespaces such as `$.*`, `radix.*`, and `animation.*` are unsupported; use direct component identifiers. Matching explicit children overlay designed descendants and keep template styles. A mismatched child structure replaces defaults, an explicit empty pair clears defaults, and a self-closing reference keeps them. Editing inherited default content writes it back as explicit JSX children. Template resolution is live when matching templates are added later. Preserve invalid source and unresolved names, inspect all diagnostics, and reload before retrying a revision conflict. A frontmatter update replaces the complete property map; preserve fields the user did not ask to remove. Store frontmatter images as exact `$ref` objects; bind Image sources to `.src` and alt properties to the Asset `.description`. Only exact direct frontmatter bindings may use `mode:"readwrite"`. After a template rename or deletion, use `migrate-content-block-template-references` to preview and confirm custom-template JSX and legacy changes across selected MDX files. A confirmed removal unwraps paired references and preserves their authored children; a self-closing reference disappears because it has none.
For an MDX-backed Content Block, use the dedicated content-source tools instead of generic prop mutations: connect, switch, inspect, edit, update frontmatter, reload, or disconnect the source. Confirm before replacing existing Body content. Prefer Markdown for standard document content; it automatically uses unique matching semantic templates. Use lowercase JSX such as `<section>` or `<svg>` for HTML or SVG that Markdown cannot express. Capitalized JSX resolves a unique stable template **Name** or a built-in MDX adapter. Add custom components to this Content Block's Templates before referencing them in MDX. The display label is independent. JSX attributes accept quoted values and bare booleans; expressions such as `{false}` are unsupported. Legacy `ws.element` and `ws:name` forms are compatibility input only. Component namespaces such as `$.*`, `radix.*`, and `animation.*` are unsupported; use direct component identifiers. Matching explicit children overlay designed descendants and keep template styles. A mismatched child structure replaces defaults, an explicit empty pair clears defaults, and a self-closing reference keeps them. Editing inherited default content writes it back as explicit JSX children. Template resolution is live when matching templates are added later. Preserve invalid source and unresolved names, inspect all diagnostics, and reload before retrying a revision conflict. A frontmatter update replaces the complete property map; preserve fields the user did not ask to remove. Store frontmatter images as exact `$ref` objects; bind editable Image sources to `.src` with explicit `binding.mode:"readwrite"` and alt properties to the Asset `.description` with `mode:"read"`. Omitting the source mode leaves the image visible but not replaceable in Content mode. Only exact direct frontmatter bindings may use `mode:"readwrite"`. After a template rename or deletion, use `migrate-content-block-template-references` to preview and confirm custom-template JSX and legacy changes across selected MDX files. A confirmed removal unwraps paired references and preserves their authored children; a self-closing reference disappears because it has none.
For an editable MDX article, use the resource to select the Content Block's source Asset (`post.data.id`), then bind article fields inside the block to its document parameter (`document.frontmatter.title`), not query-result properties. Inspect the actual document variable name first. Create writable bindings explicitly: `update-text` uses `expressionBindingMode:"readwrite"`; `bind-props` uses `binding.mode:"readwrite"`. These generic tools target persistent designed instances, such as a header outside the MDX body, not MDX-generated instances. The MDX body is editable through its source mapping; merely placing static or query-bound content inside the block does not make it editable. Use exact direct paths; property access is already safe. Direct bindings through a loaded Markdown or MDX `$ref` ending in `#frontmatter` save to the referenced file, with its write permissions enforced. Shared-record edits affect every document using that record. Computed expressions, JSON/body references, and resolved image metadata remain read-only. Follow the complete article editability checklist below before handoff.
For an editable MDX article, use the resource to select the Content Block's source Asset (`post.data.id`), then bind article fields inside the block to its document parameter (`document.frontmatter.title`), not query-result properties. Inspect the actual document variable name first. Create writable bindings explicitly: `update-text` uses `expressionBindingMode:"readwrite"`; `bind-props` uses `binding.mode:"readwrite"`. These generic tools target persistent designed instances, such as a header outside the MDX body, not MDX-generated instances. The MDX body is editable through its source mapping; merely placing static or query-bound content inside the block does not make it editable. Use exact direct paths; property access is already safe. Direct bindings through a loaded Markdown or MDX `$ref` ending in `#frontmatter` save to the referenced file, with its write permissions enforced. Shared-record edits affect every document using that record. Computed expressions and JSON/body references remain read-only. Image replacement is supported: a direct Image source binding with `mode:"readwrite"` lets the picker replace the frontmatter `$ref`, while shared Asset metadata is edited in Asset settings. Follow the complete article editability checklist below before handoff.
### Content Block completion checklist
+2 -2
View File
@@ -4,9 +4,9 @@ export const projectBuildDocs = {
"accessibility-review":
'<!-- Adapted for Webstudio MCP from Community-Access/accessibility-agents, web-accessibility-wizard/SKILL.md (MIT): https://github.com/Community-Access/accessibility-agents/blob/main/codex-skills/web-accessibility-wizard/SKILL.md -->\n\n# Webstudio Accessibility Review\n\nUse this workflow when creating or reviewing a page, component, form, menu,\ndialog, or responsive layout. It is an LLM-assisted review, not proof of WCAG\nconformance. Do not claim that a page is accessible solely because this review\nhas no findings.\n\n## Evidence First\n\n1. Read `meta.index` and use focused project tools. Do not inspect Webstudio\n source code or generated files for normal project reviews.\n2. Run `audit` with `{"scopes":["accessibility"]}` before changing\n anything. It detects deterministic metadata issues such as labels, landmark\n structure, positive tabindex values, invalid static ARIA states, and unmuted\n autoplay. Fix confirmed static findings first.\n3. Ask whether the user wants visual verification unless they explicitly\n requested it. Only after they opt in, use `preview.start` and capture each\n changed route with `screenshot` at desktop, tablet, and mobile widths. Use\n `waitForSelector` or `waitForTimeout` only when the page has an actual\n delayed ready state. If they do not opt in, continue with static evidence\n and mark visual findings as manual verification items.\n4. Use `get-page-by-path`, `list-instances`, `inspect-instance`, and focused\n prop/style reads to verify semantics and authored state that screenshots\n cannot prove.\n5. Make only supported, evidence-based fixes with semantic MCP tools. Recheck\n the affected route and the static accessibility search after every fix.\n\n## Review Areas\n\nReview these areas in priority order. Record the evidence for every finding.\n\n### 1. Names, Semantics, and Structure\n\n- Every image has purposeful alternative text or an explicitly empty alt when\n decorative. Image-submit inputs need a non-empty alt label describing their\n action.\n- For `missing-image-description` findings, inspect the rendered image in its\n page context and call `set-image-descriptions` with either a concise generated\n description or `decorative: true`. Re-run the audit after saving the decision.\n- Buttons, links, icon-only controls, and form controls have accessible names.\n- Prefer native HTML semantics over ARIA roles.\n- Non-native elements using `role="button"` or `role="link"` must be\n keyboard-focusable.\n- Use one sensible page h1, ordered heading levels, meaningful link text, and\n a main landmark.\n- Iframes have titles. Static HTML ids are unique, ARIA reference props point\n to real ids, and static boolean/select/numeric ARIA values are valid.\n- Focusable controls must not be hidden from assistive technology with\n `aria-hidden`.\n\n### 2. Keyboard and Focus\n\n- Interactive controls should be native or have a documented keyboard model.\n- Visible focus must not be removed without a visible replacement.\n- Hover-only information or controls need a keyboard-accessible equivalent.\n- Do not use positive tabindex values.\n- Mark keyboard behavior as **manual verification required** when the available\n evidence cannot prove tab order, Escape handling, or focus restoration.\n\n### 3. Dialogs, Menus, and Other Overlays\n\n- Dialogs need an accessible name and a close action.\n- Opening an overlay should move focus into it, trap focus where appropriate,\n and restore focus to its trigger on close.\n- Menus, popovers, disclosures, and tabs must expose their expanded/selected\n state and remain usable without a pointer.\n- If the current MCP/browser tools cannot exercise the interaction, report it\n as a manual verification item instead of guessing.\n\n### 4. Forms and Errors\n\n- Inputs have labels, required state, helpers, and errors associated with the\n right control.\n- Invalid controls expose `aria-invalid` when applicable.\n- Error, loading, and success feedback is not conveyed only by color or a\n transient visual toast.\n- Submit controls do not become unexplained dead ends when disabled.\n\n### 5. Visual, Responsive, Media, and Motion\n\n- At each target width, text remains readable, controls remain reachable, and\n no content is clipped, overlapped, or dependent on hover alone.\n- Do not rely only on color, position, shape, or iconography to convey meaning.\n- Keep non-text contrast, text contrast, focus indicators, and small text as\n visual review items unless measured evidence is available.\n- Videos with meaningful speech need captions; non-essential motion should\n respect reduced-motion preferences. Do not autoplay sound.\n\n### 6. Dynamic Content and Data\n\n- Loading, empty, error, and success states have understandable visible text.\n- Important dynamic updates and validation feedback need an appropriate\n announcement strategy.\n- Check repeated resource-driven content for unique labels, headings, idLine truncated
expressions:
'# Webstudio Expressions\n\nUse an expression only when a value must be computed at runtime from scoped\ndata. Use direct text and direct prop values for fixed content.\n\n## Source Format\n\nExpression-capable MCP fields receive JavaScript expression source as a JSON\nstring. Send one expression, without a `return` statement or surrounding\nfunction. For example:\n\n```json\n{ "binding": { "type": "expression", "value": "post.title ?? \\"Untitled\\"" } }\n```\n\nInside that string, use readable JavaScript syntax rather than serialized JSON.\nFor object expressions, leave identifier property names unquoted, for example\n`{ query: queryText, variables: { slug: system.params.slug } }`. Quote a property\nname only when JavaScript requires it, such as `{ "published-at": date }`. Do\nnot pass a JSON-stringified object as an expression.\n\nDo not send a fixed prop string as an expression. Use `update-props` with\n`type:"string"`. Page metadata and resource URLs accept plain fixed strings and\nnormalize them for storage. Expression-only resource headers, search parameters,\nand bodies accept `{ "type": "literal", "value": "fixed text" }` when the\nvalue is not dynamic.\n\n## Read and read-write bindings\n\nExpression bindings use `mode:"read"` by default. Use `mode:"readwrite"` only\nfor an exact direct path into the frontmatter of an MDX source connected to the\ncontaining Content Block, for example:\n\n```json\n{\n "binding": {\n "type": "expression",\n "value": "document.frontmatter.title",\n "mode": "readwrite"\n }\n}\n```\n\nThis lets Content mode save a direct edit back to that frontmatter field.\nComputed expressions, including fallbacks and concatenation, are always\nread-only. The mutation is rejected when the expression is not a direct path or\ndoes not belong to a connected Content Block document. Use the variable name\nreturned by `inspect-instance`; do not assume it is `document`.\n\nFor an MDX-backed article, use the query resource to select the Content Block\'s\nsource Asset, for example `post.data.id`. Inside the block, bind article fields\nto the block\'s document parameter, not `post.data.properties.title` or other\nequivalent query-result values. A query binding can display the correct value\nwithout supporting Content-mode edits.\n\nThe MDX body is editable through its source mapping. Designer-created elements\noutside that body, such as an article header, stay protected unless their text\nor supported props have writable frontmatter bindings. Containment in the\nContent Block alone is not enough. Use `update-text` with\n`expressionBindingMode:"readwrite"` for a designed heading\'s text, and\n`bind-props` with `binding.mode:"readwrite"` for a supported prop. These target\npersistent designed instances, not MDX-generated instances.\n\nUse direct paths for writable bindings, such as\n`document.frontmatter.title`; property access is already safe. Adding `??`\nfallbacks or formatting makes the expression read-only. Direct bindings through\nloaded Markdown or MDX `$ref` values ending in `#frontmatter` save to the\nreferenced file, with its write permissions enforced. For example, editing\n`document.frontmatter.author.name` updates the shared author file, affecting\nevery article using it while preserving the article\'s reference. JSON/body\nreferences and resolved image metadata remain read-only.\n\n### Verify the whole article, not just its body\n\nIf the user asks for full Content-mode editing, inventory every article field,\nincluding the designed header, hero image source, alternative text, captions,\nauthor details, dates, reading time, links, and custom-component content.\nVerify each field through its Content-mode UI, inspect the saved MDX or\nreferenced file, reload, then restore and verify the original value. A valid\nbinding, correct preview, or successful MCP edit is not a UI-editability test.\nReport each field as passed, failed, or not tested; do not call the article\nfully editable with required fields missing or untested.\n\nFor Image sources, bind `document.frontmatter.featureImage.src` with\n`binding.mode:"readwrite"` using `bind-props`. Content mode\'s **Choose source**\nreplaces the article\'s frontmatter image `$ref`; the resolved URL field remains\nread-only. Test this picker and the saved reference instead of assuming that\ndisplaying an image proves replacement works.\n\nAn alternative-text binding to the image\'s `.description` uses shared Asset\nmetadata. Edit it through **Choose source → asset actions → Settings →\nDescription**; that edit affects every use of the Asset. Image replacement\nand shared-description editing are separate actions, not reasons to leave\nrequired image content uneditable.\n\n### Keep editable values separate from formatting\n\nWhen a field must be editable in Content mode, do not concatenate its value\nwith labels, units, or punctuation, or wrap it in a template literal, fallback,\nor formatting call. Keep the value in its ownLine truncated
'# Webstudio Expressions\n\nUse an expression only when a value must be computed at runtime from scoped\ndata. Use direct text and direct prop values for fixed content.\n\n## Source Format\n\nExpression-capable MCP fields receive JavaScript expression source as a JSON\nstring. Send one expression, without a `return` statement or surrounding\nfunction. For example:\n\n```json\n{ "binding": { "type": "expression", "value": "post.title ?? \\"Untitled\\"" } }\n```\n\nInside that string, use readable JavaScript syntax rather than serialized JSON.\nFor object expressions, leave identifier property names unquoted, for example\n`{ query: queryText, variables: { slug: system.params.slug } }`. Quote a property\nname only when JavaScript requires it, such as `{ "published-at": date }`. Do\nnot pass a JSON-stringified object as an expression.\n\nDo not send a fixed prop string as an expression. Use `update-props` with\n`type:"string"`. Page metadata and resource URLs accept plain fixed strings and\nnormalize them for storage. Expression-only resource headers, search parameters,\nand bodies accept `{ "type": "literal", "value": "fixed text" }` when the\nvalue is not dynamic.\n\n## Read and read-write bindings\n\nExpression bindings use `mode:"read"` by default. Use `mode:"readwrite"` only\nfor an exact direct path into the frontmatter of an MDX source connected to the\ncontaining Content Block, for example:\n\n```json\n{\n "binding": {\n "type": "expression",\n "value": "document.frontmatter.title",\n "mode": "readwrite"\n }\n}\n```\n\nThis lets Content mode save a direct edit back to that frontmatter field.\nComputed expressions, including fallbacks and concatenation, are always\nread-only. The mutation is rejected when the expression is not a direct path or\ndoes not belong to a connected Content Block document. Use the variable name\nreturned by `inspect-instance`; do not assume it is `document`.\n\nFor an MDX-backed article, use the query resource to select the Content Block\'s\nsource Asset, for example `post.data.id`. Inside the block, bind article fields\nto the block\'s document parameter, not `post.data.properties.title` or other\nequivalent query-result values. A query binding can display the correct value\nwithout supporting Content-mode edits.\n\nThe MDX body is editable through its source mapping. Designer-created elements\noutside that body, such as an article header, stay protected unless their text\nor supported props have writable frontmatter bindings. Containment in the\nContent Block alone is not enough. Use `update-text` with\n`expressionBindingMode:"readwrite"` for a designed heading\'s text, and\n`bind-props` with `binding.mode:"readwrite"` for a supported prop. These target\npersistent designed instances, not MDX-generated instances.\n\nUse direct paths for writable bindings, such as\n`document.frontmatter.title`; property access is already safe. Adding `??`\nfallbacks or formatting makes the expression read-only. Direct bindings through\nloaded Markdown or MDX `$ref` values ending in `#frontmatter` save to the\nreferenced file, with its write permissions enforced. For example, editing\n`document.frontmatter.author.name` updates the shared author file, affecting\nevery article using it while preserving the article\'s reference. JSON/body\nreferences remain read-only. Image replacement is a supported reference write,\nnot a write to shared resolved metadata; use the image recipe below.\n\n### Make an article image replaceable\n\nFor `featureImage: { $ref: "./images/hero.png" }`, bind the designed Image\'s\n`src` to `document.frontmatter.featureImage.src` with explicit `mode:"readwrite"`.\nThe default `read` mode renders the image but does not let the Content-mode\neditor replace it. A disabled resolved-URL input is expected; the active\n**Choose source** picker is the replacement control.\n\nUse `bind-props` with the actual Image instance ID and document variable name:\n\n```json\n{\n "bindings": [\n {\n "instanceId": "<imageInstanceId>",\n "name": "src",\n "binding": {\n "type": "expression",\n "value": "document.frontmatter.featureImage.src",\n "mode": "readwrite"\n }\n },\n {\n "instanceId": "<imageInstanceId>",\n "name": "alt",\n "binding": {\n "type": "expression",\n "value": "document.frontmatter.featureImage.description",\n "mode": "read"\n }\n }\n ]\n}\n```\n\nThe picker saves a new `$ref` in the article. It must not save a resolved URL\nstring or modify the original shared Asset. Shared alternative text uses\n**Choose source → asset actions → Settings → Description** instead.\n\nIf the picker is absent or disabled, first inspect the source binding\'s mode,\ndocument scope, loaded `$ref`, and permissions. Do not infer that replacement\nis unsupported from a correctly rendered image or the disabled URL input.\n\n### Verify the whole article, not just its body\n\nIf the user aLine truncated
"mcp-startup-guidance":
'If you are inside the Webstudio monorepo, use the local CLI exactly as `node packages/cli/local.js ...` as your first command path. Do not use `packages/cli/bin.js` for local source-tree work; it is the packaged build entry and may use stale built output. Before editing a Webstudio project, do one small discovery step, then act. For delegated design-system or “use every component” tasks, the first MCP command is `workflow.next {"goal":"design-system-page"}`; report that returned checkpoint to the parent/user and stop until continued. For a simple authored/styled section, the intended path is literal: call `meta.index`, call `meta.get-more-tools` with `{"tools":["insert-fragment"]}`, read the target parent id with `list-pages`/`get-page-by-path`/`list-instances` only if needed, then call `insert-fragment`. Prefer `insert-fragment` for authored/styled sections; use `insert-component` only when inserting one automatic component template. Do not grep source files, dump full MCP resources, or write parser scripts before trying focused MCP calls. Good first calls are `meta.index` for orientation, `meta.guide` for a goal workflow, `workflow.next` for one bounded delegated phase, `meta.get-more-tools` for exact tool schemas, and `components.coverage-plan`, `components.coverage-insert-next`, `components.find`, or `components.get` for component work. Do not call every discovery tool up front. For delegated or non-streaming agents whose parent cannot see live stderr/stdout, treat each parent-visible checkpoint as the unit of work. If the parent asks for status within 30 seconds, run exactly one shortcut command such as `webstudio meta.index` or one explicit `webstudio mcp single-op-call` command, report its command/result, and wait for the parent before the next MCP command. Do not run long shell loops of shortcut or `webstudio mcp single-op-call` commands; they hide progress from the parent. Do not take a broad task such as creating a full design-system page as one execution unit. Instead call `workflow.next {"goal":"design-system-page"}`, report the returned phase/checkpoint to the parent, wait until the parent continues, call `checkpoint.ack {"reported":true,"continueAfterReport":true,"summary":"<what you reported>"}`, complete exactly that bounded phase, and return: discovery, page creation, one dry-run JSX section, one committed JSX section, one `components.coverage-insert-next` call, or one presentation pass. Phase commands do not include nextPhase in their own output. After the parent continues, acknowledge the previous checkpoint first, then call `workflow.next` with the next phase. For design-system or “use every component” tasks, start with `workflow.next`, acknowledge its checkpoint only after parent/user continuation, then run compact `components.coverage-plan`, checkpoint, create the page, checkpoint, then call `components.coverage-insert-next` once per coverage checkpoint, and finish with the `presentation-pass` workflow phase. Coverage 72/72 is necessary but not sufficient: the page must be organized into styled, real-world design-system examples instead of raw unstyled component dumps. Request component coverage details with `components.coverage-plan {"detail":"roots"}` or `components.coverage-plan {"detail":"parts"}` only when needed. `list-pages` does not accept `detail`; use `list-pages {}` or `get-page-by-path` for page lookup. Read overview resources such as `webstudio://project/guide`, `webstudio://project/tools-overview`, and `webstudio://project/components-overview` only when focused tools are insufficient. Do not dump or parse full resources such as `webstudio://project/tools` or `webstudio://project/components` unless the focused tools are insufficient. Run one-shot shortcut or explicit `webstudio mcp single-op-call` commands sequentially against the same linked `.webstudio` folder. For experiments, pass `--dry-run` to local-capable mutations. Copying a `.webstudio` folder is not an isolated project clone; `.webstudio/config.json` still points to the same remote project, so non-dry-run mutations can commit to that project. If a one-shot call returns checkpoint.required, the CLI persists `CHECKPOINT_REQUIRED` across later one-shot calls until you report the checkpoint, wait until continued, and call `checkpoint.ack {"reported":true,"continueAfterReport":true,"summary":"<what you reported>"}`. If you receive `PROJECT_SESSION_BUSY`, another CLI/MCP process is updating the local session; wait a moment and retry sequentially. Complete one bounded phase and return a checkpoint before continuing. Follow the guide: read ids and Builder breakpoints first, use focused component discovery for component ids, props, and content model composition, prefer semantic tools over `apply-patch`, use direct value tools for fixed text/props, use bindings only for dynamic expressions/resources/actions, page metadata and fixed resource URLs accept plain strings, put page/resource update fields under `va Line truncated
'If you are inside the Webstudio monorepo, use the local CLI exactly as `node packages/cli/local.js ...` as your first command path. Do not use `packages/cli/bin.js` for local source-tree work; it is the packaged build entry and may use stale built output. Before editing a Webstudio project, do one small discovery step, then act. For delegated design-system or “use every component” tasks, the first MCP command is `workflow.next {"goal":"design-system-page"}`; report that returned checkpoint to the parent/user and stop until continued. For a simple authored/styled section, the intended path is literal: call `meta.index`, call `meta.get-more-tools` with `{"tools":["insert-fragment"]}`, read the target parent id with `list-pages`/`get-page-by-path`/`list-instances` only if needed, then call `insert-fragment`. Prefer `insert-fragment` for authored/styled sections; use `insert-component` only when inserting one automatic component template. Do not grep source files, dump full MCP resources, or write parser scripts before trying focused MCP calls. Good first calls are `meta.index` for orientation, `meta.guide` for a goal workflow, `workflow.next` for one bounded delegated phase, `meta.get-more-tools` for exact tool schemas, and `components.coverage-plan`, `components.coverage-insert-next`, `components.find`, or `components.get` for component work. Do not call every discovery tool up front. For delegated or non-streaming agents whose parent cannot see live stderr/stdout, treat each parent-visible checkpoint as the unit of work. If the parent asks for status within 30 seconds, run exactly one shortcut command such as `webstudio meta.index` or one explicit `webstudio mcp single-op-call` command, report its command/result, and wait for the parent before the next MCP command. Do not run long shell loops of shortcut or `webstudio mcp single-op-call` commands; they hide progress from the parent. Do not take a broad task such as creating a full design-system page as one execution unit. Instead call `workflow.next {"goal":"design-system-page"}`, report the returned phase/checkpoint to the parent, wait until the parent continues, call `checkpoint.ack {"reported":true,"continueAfterReport":true,"summary":"<what you reported>"}`, complete exactly that bounded phase, and return: discovery, page creation, one dry-run JSX section, one committed JSX section, one `components.coverage-insert-next` call, or one presentation pass. Phase commands do not include nextPhase in their own output. After the parent continues, acknowledge the previous checkpoint first, then call `workflow.next` with the next phase. For design-system or “use every component” tasks, start with `workflow.next`, acknowledge its checkpoint only after parent/user continuation, then run compact `components.coverage-plan`, checkpoint, create the page, checkpoint, then call `components.coverage-insert-next` once per coverage checkpoint, and finish with the `presentation-pass` workflow phase. Coverage 72/72 is necessary but not sufficient: the page must be organized into styled, real-world design-system examples instead of raw unstyled component dumps. Request component coverage details with `components.coverage-plan {"detail":"roots"}` or `components.coverage-plan {"detail":"parts"}` only when needed. `list-pages` does not accept `detail`; use `list-pages {}` or `get-page-by-path` for page lookup. Read overview resources such as `webstudio://project/guide`, `webstudio://project/tools-overview`, and `webstudio://project/components-overview` only when focused tools are insufficient. Do not dump or parse full resources such as `webstudio://project/tools` or `webstudio://project/components` unless the focused tools are insufficient. Run one-shot shortcut or explicit `webstudio mcp single-op-call` commands sequentially against the same linked `.webstudio` folder. For experiments, pass `--dry-run` to local-capable mutations. Copying a `.webstudio` folder is not an isolated project clone; `.webstudio/config.json` still points to the same remote project, so non-dry-run mutations can commit to that project. If a one-shot call returns checkpoint.required, the CLI persists `CHECKPOINT_REQUIRED` across later one-shot calls until you report the checkpoint, wait until continued, and call `checkpoint.ack {"reported":true,"continueAfterReport":true,"summary":"<what you reported>"}`. If you receive `PROJECT_SESSION_BUSY`, another CLI/MCP process is updating the local session; wait a moment and retry sequentially. Complete one bounded phase and return a checkpoint before continuing. Follow the guide: read ids and Builder breakpoints first, use focused component discovery for component ids, props, and content model composition, prefer semantic tools over `apply-patch`, use direct value tools for fixed text/props, use bindings only for dynamic expressions/resources/actions, page metadata and fixed resource URLs accept plain strings, put page/resource update fields under `va Line truncated
} as const;
export type ProjectBuildDocName = keyof typeof projectBuildDocs;
+50 -12
View File
@@ -68,7 +68,51 @@ loaded Markdown or MDX `$ref` values ending in `#frontmatter` save to the
referenced file, with its write permissions enforced. For example, editing
`document.frontmatter.author.name` updates the shared author file, affecting
every article using it while preserving the article's reference. JSON/body
references and resolved image metadata remain read-only.
references remain read-only. Image replacement is a supported reference write,
not a write to shared resolved metadata; use the image recipe below.
### Make an article image replaceable
For `featureImage: { $ref: "./images/hero.png" }`, bind the designed Image's
`src` to `document.frontmatter.featureImage.src` with explicit `mode:"readwrite"`.
The default `read` mode renders the image but does not let the Content-mode
editor replace it. A disabled resolved-URL input is expected; the active
**Choose source** picker is the replacement control.
Use `bind-props` with the actual Image instance ID and document variable name:
```json
{
"bindings": [
{
"instanceId": "<imageInstanceId>",
"name": "src",
"binding": {
"type": "expression",
"value": "document.frontmatter.featureImage.src",
"mode": "readwrite"
}
},
{
"instanceId": "<imageInstanceId>",
"name": "alt",
"binding": {
"type": "expression",
"value": "document.frontmatter.featureImage.description",
"mode": "read"
}
}
]
}
```
The picker saves a new `$ref` in the article. It must not save a resolved URL
string or modify the original shared Asset. Shared alternative text uses
**Choose source → asset actions → Settings → Description** instead.
If the picker is absent or disabled, first inspect the source binding's mode,
document scope, loaded `$ref`, and permissions. Do not infer that replacement
is unsupported from a correctly rendered image or the disabled URL input.
### Verify the whole article, not just its body
@@ -81,17 +125,11 @@ binding, correct preview, or successful MCP edit is not a UI-editability test.
Report each field as passed, failed, or not tested; do not call the article
fully editable with required fields missing or untested.
For Image sources, bind `document.frontmatter.featureImage.src` with
`binding.mode:"readwrite"` using `bind-props`. Content mode's **Choose source**
replaces the article's frontmatter image `$ref`; the resolved URL field remains
read-only. Test this picker and the saved reference instead of assuming that
displaying an image proves replacement works.
An alternative-text binding to the image's `.description` uses shared Asset
metadata. Edit it through **Choose source → asset actions → Settings →
Description**; that edit affects every use of the Asset. Image replacement
and shared-description editing are separate actions, not reasons to leave
required image content uneditable.
For images, use the recipe above and verify the picker, changed `$ref`, reload,
and restoration with an approved temporary replacement. Confirm unrelated MDX
and the original shared Asset remain unchanged. A metadata edit or a disabled
URL input does not test image replacement. If the replacement test is not
authorized, record it as not tested rather than passed.
### Keep editable values separate from formatting
@@ -6,4 +6,4 @@ When `report-issue` is available and the user explicitly asks to report a proble
Content Block work is not complete after one editable heading works. For every creation, migration, or repair, with or without MDX, inventory all intended editor-owned fields and their write destinations before implementation. Use semantic controls (calendar for dates, image picker for image replacement), keep fixed wording separate from direct writable bindings, and preserve existing field types and wording. Verify each field through Content mode, saved data, and reload; restore test values. Report passed, failed, or not tested per field. Missing or read-only required controls are unfinished requirements. Never substitute a correct preview or MCP write for the UI test.
For MDX articles, include the designed header, reading time, dates, images, alternative text, links, author fields, and custom-component content—not just the body. Replacing an image changes the article's frontmatter image `$ref`, not shared resolved Asset metadata. Do not defer image replacement because shared alternative text needs a decision. Follow the expressions guide's whole-article verification checklist before handoff.
For MDX articles, include the designed header, reading time, dates, images, alternative text, links, author fields, and custom-component content—not just the body. For a designed Image, use `bind-props` with `src` bound directly to `document.frontmatter.featureImage.src` and explicit `binding.mode:"readwrite"`; the default read-only mode can render correctly while hiding replacement controls. **Choose source** changes the article's image `$ref`, not shared resolved Asset metadata; the disabled URL input is expected. Keep the `.description` alt binding read-only and edit shared Description through Asset settings. Inspect binding mode, document scope, loaded reference, and permissions before claiming image replacement is unsupported. Follow the expressions guide's image recipe and whole-article verification checklist before handoff.