@bettercms-ai/mcp 0.83.0 → 0.83.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +86 -86
- package/SKILL.md +160 -160
- package/dist/index.js +38 -9
- package/dist/index.js.map +1 -1
- package/dist/kit-catalog.json +1509 -1509
- package/dist/skills/bettercms/SKILL.md +206 -206
- package/dist/skills/bettercms/references/accessibility.md +171 -171
- package/dist/skills/bettercms/references/animation.md +296 -296
- package/dist/skills/bettercms/references/astro.md +148 -148
- package/dist/skills/bettercms/references/bindings.md +366 -366
- package/dist/skills/bettercms/references/componentize.md +185 -185
- package/dist/skills/bettercms/references/components.md +415 -415
- package/dist/skills/bettercms/references/content-experiments.md +62 -62
- package/dist/skills/bettercms/references/content-modeling.md +382 -382
- package/dist/skills/bettercms/references/detection.md +465 -465
- package/dist/skills/bettercms/references/dock-input.md +121 -121
- package/dist/skills/bettercms/references/editor-chrome.md +92 -92
- package/dist/skills/bettercms/references/external-content.md +78 -78
- package/dist/skills/bettercms/references/finish-site.md +377 -377
- package/dist/skills/bettercms/references/forms-and-interactions.md +245 -245
- package/dist/skills/bettercms/references/frameworks.md +159 -159
- package/dist/skills/bettercms/references/getting-started.md +156 -156
- package/dist/skills/bettercms/references/integrations.md +364 -364
- package/dist/skills/bettercms/references/kit-catalog.md +3259 -3259
- package/dist/skills/bettercms/references/kit-scenarios.md +712 -712
- package/dist/skills/bettercms/references/localization.md +85 -85
- package/dist/skills/bettercms/references/media-and-brand.md +181 -181
- package/dist/skills/bettercms/references/next.md +189 -189
- package/dist/skills/bettercms/references/other-frameworks.md +85 -85
- package/dist/skills/bettercms/references/portable-text.md +213 -213
- package/dist/skills/bettercms/references/programmatic-seo.md +98 -98
- package/dist/skills/bettercms/references/publishing.md +289 -289
- package/dist/skills/bettercms/references/seo.md +357 -357
- package/dist/skills/bettercms/references/shopify-headless.md +52 -52
- package/dist/skills/bettercms/references/site-blueprints.md +895 -895
- package/dist/skills/bettercms/references/site-review.md +74 -74
- package/dist/skills/bettercms/references/worked-examples-advanced.md +509 -509
- package/dist/skills/bettercms/references/worked-examples.md +885 -885
- package/dist/skills/bettercms/references/write-limits.md +217 -217
- package/package.json +1 -1
|
@@ -1,206 +1,206 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: bettercms
|
|
3
|
-
description: "BetterCMS: build, convert, import, edit, publish and verify BetterCMS sites. Use whenever the user names BetterCMS or its MCP, or the repo has @bettercms-ai/* packages, data-bcms- attributes, bcms-content.json or bcms-rebuild.yml, even when they only say 'make it editable', 'import my site', 'convert this repo', 'add a section', 'fix the schema' or 'publish'. Covers setup, the finish-site workflow, content modeling, components, click-to-edit bindings, Portable Text, media, forms, SEO and launch review. Moving off another CMS: bettercms-migrate. ABM campaigns: bettercms-abm."
|
|
4
|
-
license: MIT
|
|
5
|
-
metadata:
|
|
6
|
-
author: bettercms
|
|
7
|
-
version: "0.3.0"
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
# BetterCMS
|
|
11
|
-
|
|
12
|
-
The BetterCMS MCP serves its own doctrine, so this skill carries only what the server cannot see:
|
|
13
|
-
your repo's framework wiring, binding attributes, env names, stored value shapes and the traps
|
|
14
|
-
that only show up in code. Read doctrine from the MCP, never from memory:
|
|
15
|
-
|
|
16
|
-
- Schema, sections, variants, publish order: resource `bettercms://playbook/schema` (§1–§14).
|
|
17
|
-
- Content sidebar organisation: resource `bettercms://playbook/structure`.
|
|
18
|
-
- Section patterns (149 worked kit entries by category and edge tag): resource `bettercms://kit`.
|
|
19
|
-
- Guided flows: the `studio` prompt routes to the rest (`convert_site` prompt,
|
|
20
|
-
`build_site` prompt, `componentize_site` prompt, `propose_schema` prompt, `new_page` prompt,
|
|
21
|
-
`new_component` prompt, `new_form` prompt, `seo_optimize` prompt, `import-site` prompt,
|
|
22
|
-
`field-ui` prompt, `edit_layout` prompt for the Global Layout, `generate_landing_pages` prompt
|
|
23
|
-
for page families from data).
|
|
24
|
-
- Import and modelling rule ids: `CM-01`…`CM-83` in the content-modeling standard.
|
|
25
|
-
|
|
26
|
-
## Start here
|
|
27
|
-
|
|
28
|
-
Setting up a project, or asked to "Continue BetterCMS setup"? Read
|
|
29
|
-
[references/getting-started.md](references/getting-started.md) first: it owns the setup phases
|
|
30
|
-
and the resume check. For any other task, read the one reference the table below names.
|
|
31
|
-
|
|
32
|
-
## Connecting (before your first MCP call)
|
|
33
|
-
|
|
34
|
-
Listing tools needs no sign-in; the first tool **call** does.
|
|
35
|
-
|
|
36
|
-
1. **A 401 on the first call is the sign-in, not an error.** The client opens a browser sign-in
|
|
37
|
-
from the `WWW-Authenticate` header. Tell the user to approve it, then retry that same call.
|
|
38
|
-
2. **If `list_projects` lacks the project id you were given, stop and say so.** Consent binds to
|
|
39
|
-
the workspace the dashboard had active; ask the user to re-authenticate in the right one.
|
|
40
|
-
Never continue in whichever project IS listed: that writes into someone else's site.
|
|
41
|
-
3. **Pass `projectId` on every project tool, and never ask the user to re-scope.** A
|
|
42
|
-
workspace-wide connection reaches every project by naming it per call.
|
|
43
|
-
4. **A refusal for access: call `whoami` first.** It names the principal, the workspace, the
|
|
44
|
-
scope (project or workspace) and, where visible, the grants (publish, code and deploy,
|
|
45
|
-
sidebar schema), so you can tell the user which one is missing.
|
|
46
|
-
5. **"Invalid tool parameters" is the client, not BetterCMS.** A client with tool search (Claude
|
|
47
|
-
Code) lists most of the 150 tools by name and loads a schema on demand; a call to a tool whose
|
|
48
|
-
schema it has not loaded is refused before it is sent. Load the tool with the client's tool
|
|
49
|
-
search, every tool the step needs in one search, then make the same call again. Never change
|
|
50
|
-
the arguments because of it. The tools a setup starts with are always loaded.
|
|
51
|
-
6. **Unsure how a feature works: `search_docs` before guessing.** A tool that fails oddly, a
|
|
52
|
-
capability you needed and did not have, or docs that misled you: `give_feedback`, and tell the
|
|
53
|
-
user you sent it.
|
|
54
|
-
|
|
55
|
-
## Invariants
|
|
56
|
-
|
|
57
|
-
These hold on every task. The reference in brackets has the detail and the codes.
|
|
58
|
-
|
|
59
|
-
1. **Confirm the bound project before any write**: §9 of the schema playbook, then `get_project`.
|
|
60
|
-
Its `authoringPreference` defaults to components (recorded by a deploy, a promote or setup)
|
|
61
|
-
and is never asked; the owner can switch it to fields.
|
|
62
|
-
2. **Never create SEO fields** (§5b). Page and entry meta are native columns. [seo.md]
|
|
63
|
-
3. **A page is a list of sections**, never loose top-level blocks, and never a nav, footer or
|
|
64
|
-
modal: chrome is the Layout. A call to action is one `button` field, never a text field
|
|
65
|
-
beside a link field. [components.md, content-modeling.md]
|
|
66
|
-
4. **Nothing is live until it is published, and a page is not its content.** A draft form,
|
|
67
|
-
component or entry renders nothing live. Read `warnings` on every write: `ENTRY_STILL_DRAFT`
|
|
68
|
-
and `ENTRY_SEED_FAILED` mean content did not ship. An answer that leads with `held`, and a
|
|
69
|
-
publish reading `outcome.status: "partial"`, did not reach the site: do the action it names
|
|
70
|
-
before you report it.
|
|
71
|
-
[publishing.md]
|
|
72
|
-
5. **Name the folder system every time you say "folder"**: Content sidebar folders never touch a
|
|
73
|
-
URL, URL page folders are part of the path, media folders organise assets.
|
|
74
|
-
[content-modeling.md]
|
|
75
|
-
6. **Headless projects are built by their host.** Never `deploy_project`, `deploy_to_host` or
|
|
76
|
-
`create_deploy_upload` there, never add `bcms-rebuild.yml`; deploy with
|
|
77
|
-
`npx @bettercms-ai/cli@latest deploy --to <host>`, or push to the repo the host builds.
|
|
78
|
-
Done = `receipt.frontEnd` closed. [getting-started.md]
|
|
79
|
-
7. **Every refusal has a code. Report it; do not retry blind.** The same call returns the same
|
|
80
|
-
code. Change the input or stop.
|
|
81
|
-
8. **Media is served by the backend that owns the asset ids.** `mediaUrl` is `mediaBaseUrl` from
|
|
82
|
-
`get_project`; never hardcode, re-point or re-host media, and never read a bucket or key.
|
|
83
|
-
[frameworks.md]
|
|
84
|
-
9. **Bind the leaf that renders the value, one address per element.** Attribute values ride
|
|
85
|
-
`data-bcms-props`; `data-bcms-kind` declares the container, and the MODEL picks the editor.
|
|
86
|
-
Inside an instance the address is `<instanceId>__overrides.<key>`; chrome uses
|
|
87
|
-
`data-bcms-layout-field`. [bindings.md]
|
|
88
|
-
10. **Declared mode is a switch you flip** with `set_binding_mode` after the stamped build reports
|
|
89
|
-
clean: push, release, report clean, flip, release again. [bindings.md]
|
|
90
|
-
11. **A field is not editable because it exists.** It is editable when its value renders from the
|
|
91
|
-
CMS on a bound leaf and an edit shows in preview and after publish.
|
|
92
|
-
12. **Bulk work runs as code, not as a chain of tool calls.** Propose the mapping and dry-run it
|
|
93
|
-
before a high-volume write; use the MCP for state, targeted fixes and reports.
|
|
94
|
-
13. **A build makes a site live, not editable.** It brings in SEO and meta, media, the brand and
|
|
95
|
-
the models `bcms-content.json` declares. Pages, collections, forms, bindings and components
|
|
96
|
-
are `editor_setup`'s: run it after an import or a rebuild (`get_deploy_status` `editorSetup`
|
|
97
|
-
`never` or `stale`). It also fills missing meta, merges identical components and adopts
|
|
98
|
-
declared bindings when proven; do only what get_next_steps still lists. [getting-started.md]
|
|
99
|
-
|
|
100
|
-
## What you do, and what only the owner does
|
|
101
|
-
|
|
102
|
-
The MCP acts as the signed-in person. Some decisions are theirs by design: no tool makes them,
|
|
103
|
-
and saying you made one is a false report. Name each as an action in your final message.
|
|
104
|
-
|
|
105
|
-
| Only the owner | Where |
|
|
106
|
-
|---|---|
|
|
107
|
-
| Authoring preference and media delivery answers | you ask; `set_authoring_preference`, `set_media_delivery` |
|
|
108
|
-
| Visual Approval of a component, CI (GitHub Actions) validation | dashboard |
|
|
109
|
-
| Approving a generated job or a flagged ABM entry | the user's explicit yes before `approve_ai_job` / `approve_campaign_entries` |
|
|
110
|
-
| Brand colours and typography; URL page folders; unpublishing a form | dashboard |
|
|
111
|
-
| Hosting **Run as a server app**; form integrations; the Turnstile secret | dashboard |
|
|
112
|
-
| `llms.txt` and Markdown twin switches | dashboard, SEO permission |
|
|
113
|
-
| Publishing to production | the user's authorization, then the tools |
|
|
114
|
-
|
|
115
|
-
Secrets never go in a tool call, a `PUBLIC_` variable or a client bundle. A 403
|
|
116
|
-
`SCHEMA_ACCESS_REQUIRED` means the person lacks Admin or Developer access: stop and tell them.
|
|
117
|
-
|
|
118
|
-
## Which reference to read
|
|
119
|
-
|
|
120
|
-
Read one reference per phase. Each is self-contained; a second one is needed only when the task
|
|
121
|
-
crosses into its topic. When this skill is not installed, the MCP serves the same files as
|
|
122
|
-
resources: `bettercms://skill/bettercms` for this file, and each reference under its file stem
|
|
123
|
-
(`bettercms://skill/seo` for seo.md).
|
|
124
|
-
|
|
125
|
-
| Task | Reference | Read when | Keywords |
|
|
126
|
-
|---|---|---|---|
|
|
127
|
-
| Set up or resume a project | [getting-started.md](references/getting-started.md) | first contact, or "Continue BetterCMS setup" | setup, resume, onboarding, connect, import my site, headless, own front end, SDK, CLI |
|
|
128
|
-
| Finish an imported or converted site | [finish-site.md](references/finish-site.md) | a convert or build job; "make it fully editable"; the gap ledger | make it editable, finish, gap ledger, convert |
|
|
129
|
-
| Move content out of another CMS (Cosmic, Contentful, Sanity, Strapi, Prismic, WordPress…) | [external-content.md](references/external-content.md) | a CMS SDK in package.json; `envWarning` on import; pages that render empty without a third-party key | Contentful, Sanity, Strapi, envWarning, missing key, empty pages |
|
|
130
|
-
| Read a source site before modelling it | [detection.md](references/detection.md) | converting from a URL or built HTML; deciding what a band, a repeat or a value is | detect, classify, section, repeat, global, carousel clone, hidden state |
|
|
131
|
-
| Pages vs collections, folders, fields, schema changes | [content-modeling.md](references/content-modeling.md) | modelling a route family; a model write returns 409 | schema, model, collection, field, folder, rename, remove field, listing, filter, locked field |
|
|
132
|
-
| Dock layout: groups, rows, tabs, icons, item names, showIf order | [editor-chrome.md](references/editor-chrome.md) | after any import, convert, componentize or extract (the gate's `dock` row); a `dock-*` rule; the `field-ui` prompt | dock, fieldset, tab, group, itemLabel, showIf, field-ui |
|
|
133
|
-
| A custom input for one field in the dock: when, the user's approval, the contract | [dock-input.md](references/dock-input.md) | `get_next_steps` lists `dock-input-candidate`; a 409 `input_needs_confirmation` | custom input, ui.input, dock input, confirmed, swatch |
|
|
134
|
-
| What the server does and does not check on a write | [write-limits.md](references/write-limits.md) | before relying on a limit; reading a refused write; a bulk load or re-run | validation, maxLength, unique, 400, refused write, dry run, externalKey, upsert, re-run |
|
|
135
|
-
| Plan a site by business type | [site-blueprints.md](references/site-blueprints.md) | the IA of a known site type, with its collections, forms and structured data | new site, IA, portfolio, agency, corporate, SaaS, ecommerce, directory, blog, docs, restaurant, events, course, jobs, real estate, nonprofit, multi-brand |
|
|
136
|
-
| Components, props, variants, component publish codes | [components.md](references/components.md) | creating, swapping, publishing or validating a component | component, prop, variant, sectionType, publish component |
|
|
137
|
-
| Which kit pattern fits a section, and its shape and pitfalls, by category and edge tag | [kit-scenarios.md](references/kit-scenarios.md) | before designing any section's fields or props; a band detection.md classified | kit, pattern, scenario, edge tag, events, locations, calculator, map, chart, docs, team, bento, slots, personalization, localized |
|
|
138
|
-
| One section, source HTML to bound template: hero, feature grid, pricing table, testimonials, FAQ, bento | [worked-examples.md](references/worked-examples.md) | you want the whole path for one section in production shapes | example, hero, pricing, FAQ, testimonial, source to schema |
|
|
139
|
-
| The same for an article entry, navigation in the Global Layout, tabs holding columns | [worked-examples-advanced.md](references/worked-examples-advanced.md) | a collection entry with a body, site chrome, or nested blocks | example, blog post, document body, mega menu, tabs, columns |
|
|
140
|
-
| The modelled section closest to the one you are building: schema, HTML signals, mcp steps, pitfalls | [kit-catalog.md](references/kit-catalog.md) | before designing a section or its props; matching source HTML to a known pattern | kit, catalogue, edge tag, section pattern, bento, localized, personalization, a11y, responsive |
|
|
141
|
-
| Componentize a derived site | [componentize.md](references/componentize.md) | `get_site_composition` shows pages made of fields only | componentize, sections, fields-only, get_componentize_plan, BcmsSections, --sections |
|
|
142
|
-
| Click-to-edit attributes, addresses, declared mode | [bindings.md](references/bindings.md) | `grep -rl "data-bcms-" src` finds files; a value the editor cannot select | data-bcms-field, click to edit, binding report, stega, declared |
|
|
143
|
-
| Animated sites: GSAP, ScrollTrigger, split text, Motion, Lenis, Locomotive, three.js and WebGL, marquees, carousels, Lottie, hydrated islands, and what must stand down in the editor's canvas (`inEditor()`) | [animation.md](references/animation.md) | `package.json` lists `gsap`, `lenis`, `locomotive-scroll`, `framer-motion` or `motion`, `three`, `swiper` or a text splitter; a publish refused with `SPLIT_PATTERN_UNKNOWN` or `ISLAND_PROPS_UNMATCHED`; a `client-only-island` gate exception | animation, GSAP, ScrollTrigger, SplitText, Lenis, Framer Motion, marquee, Swiper, Lottie, island, client:only, data-bcms-split |
|
|
144
|
-
| Wiring, env, hosting modes, media host, snapshots | [frameworks.md](references/frameworks.md) | `package.json` lists an adapter; `bcms-content.json` exists | hosting, headless, env, codegen, types, revalidate, snapshot |
|
|
145
|
-
| Astro adapter | [astro.md](references/astro.md) | the repo has `astro.config.*` | astro.config, Astro, BcmsBlocks, getStaticPaths |
|
|
146
|
-
| Next.js adapter | [next.md](references/next.md) | the repo has `next.config.*` | next.config, Next.js, App Router, ISR, notFound, static export |
|
|
147
|
-
| Nuxt, SvelteKit, React Router, Vite: no adapter | [other-frameworks.md](references/other-frameworks.md) | neither `astro.config.*` nor `next.config.*`; `nuxt.config.*`, `svelte.config.*`, `react-router.config.*` | Nuxt, SvelteKit, React Router, Vite, createClient |
|
|
148
|
-
| Rich text and field types | [portable-text.md](references/portable-text.md) | writing a richtext value; converting HTML or Markdown | rich text, Portable Text, richtext, HTML, Markdown |
|
|
149
|
-
| Brand kit, tokens, fonts, logo, images, icons | [media-and-brand.md](references/media-and-brand.md) | design fidelity, alt text, a logo or favicon change | brand, tokens, fonts, logo, image, alt text, favicon |
|
|
150
|
-
| Connect a vendor with a public API (jobs board, store, CRM, video): declare, approve, call, recipes | [integrations.md](references/integrations.md) | the user names Greenhouse, JobDiva, Shopify, HubSpot, Zoom, Apollo or any API; a 409 `integration_not_approved` | integration, API key, Greenhouse, JobDiva, Shopify, HubSpot, Zoom, Apollo, sync, vendor, token |
|
|
151
|
-
| Forms, menus, accordions, modals, consent | [forms-and-interactions.md](references/forms-and-interactions.md) | attaching or verifying a form; an interactive section | form, submission, Turnstile, modal, accordion, menu |
|
|
152
|
-
| Languages, locale prefixes, translation, hreflang | [localization.md](references/localization.md) | the build serves `/fr`-style prefixes; `locale-unvarianted` in a binding report | language, locale, /fr, translate, hreflang, i18n |
|
|
153
|
-
| SEO and AEO | [seo.md](references/seo.md) | meta, JSON-LD, sitemap, robots, redirects, AI crawlers, `list_seo_issues` | SEO, meta, JSON-LD, schema.org, sitemap, robots, OG image, redirect, 410, llms.txt |
|
|
154
|
-
| Accessibility: alt text, form labels, contrast, the audit codes and the manual checks | [accessibility.md](references/accessibility.md) | writing alt text; building a form; before reporting a site done | accessibility, WCAG, alt text, decorative, label, contrast, captions |
|
|
155
|
-
| Page families from data | [programmatic-seo.md](references/programmatic-seo.md) | a keyword list or CSV should become pages | programmatic SEO, CSV, dataset, landing pages, glossary |
|
|
156
|
-
| Publish, deploy, roll back, reconcile a re-import; add a section to a page or set its spacing | [publishing.md](references/publishing.md) | a release; a code push that conflicts with CMS edits; "add a section here", "more padding on this section"; a write that answers `held` or a publish that reads `partial` | publish, deploy, rollback, sync, webhook, schedule, automation, add section, insertSection, sectionStyle, spacing, padding, margin, held, partial |
|
|
157
|
-
| Read-only launch review | [site-review.md](references/site-review.md) | "is this ready to launch?" without fixing | launch review, audit, is it ready, QA |
|
|
158
|
-
| A/B tests on section variants | [content-experiments.md](references/content-experiments.md) | an experiment plan or readout | A/B test, experiment, variant test |
|
|
159
|
-
| Headless Shopify storefront | [shopify-headless.md](references/shopify-headless.md) | Shopify owns commerce, BetterCMS the editorial | Shopify, Hydrogen, storefront, product |
|
|
160
|
-
|
|
161
|
-
Other sites move into BetterCMS with the `bettercms-migrate` skill; per-account campaign pages
|
|
162
|
-
are the `bettercms-abm` skill.
|
|
163
|
-
|
|
164
|
-
## Context budget
|
|
165
|
-
|
|
166
|
-
A whole-site job outlives one context window. Spend it on the site, not on re-reading.
|
|
167
|
-
|
|
168
|
-
- Start from the receipt: `get_next_steps` returns `receipt.done`, `receipt.missing` and
|
|
169
|
-
`receipt.nextAction`. Plan the session from it, not from re-reading the site.
|
|
170
|
-
- Hold SKILL.md plus only the ONE reference the current phase needs; drop it when the phase ends.
|
|
171
|
-
- Ask the MCP for summaries before reading files: `get_site_composition`, `get_binding_report`
|
|
172
|
-
and `get_next_steps` answer "what is left" in a few hundred tokens, where built HTML or a whole
|
|
173
|
-
repo costs tens of thousands.
|
|
174
|
-
- Run bulk edits through the codemod (`npx @bettercms-ai/convert`), not file-by-file hand edits
|
|
175
|
-
in context; read its receipt, not the diff.
|
|
176
|
-
- Keep the gap ledger in `.bettercms/ledger.json` in the repo (shape in finish-site.md) and
|
|
177
|
-
re-read it after a reset instead of carrying it in chat.
|
|
178
|
-
- Where your agent supports subagents, fan out per-route verification and have each return only
|
|
179
|
-
its verdict and the failing evidence.
|
|
180
|
-
- Pass the `projectId` you already have; never re-list projects to find it again.
|
|
181
|
-
- After a reset, say "Continue BetterCMS setup": the resume check rebuilds state from the MCP and
|
|
182
|
-
the ledger.
|
|
183
|
-
|
|
184
|
-
## Verify loop (after every change, before you say "done")
|
|
185
|
-
|
|
186
|
-
Stop at the first step that is not clean, fix, then restart. A report that does not exist yet is
|
|
187
|
-
"not yet generated", which is not the same as dirty; say which.
|
|
188
|
-
|
|
189
|
-
1. **Fetch the live URL**, cache-busted: a 200 whose body contains copy you just published. The
|
|
190
|
-
steps below read the control plane, and all of them can be green on a site that answers 404.
|
|
191
|
-
2. `get_binding_report` for every route you touched: `unaddressable` under 2%, and, where the
|
|
192
|
-
source declares its bindings, `coverage.pending` empty and `mode: "declared"`. `refreshReason: "never-generated"` means no BetterCMS
|
|
193
|
-
release wrote one (on headless none ever will, so step 1 is the proof); `"outdated"` means
|
|
194
|
-
the next release rewrites it.
|
|
195
|
-
3. `get_site_composition`: every page you touched is made of sections, with the intended
|
|
196
|
-
components.
|
|
197
|
-
4. `list_seo_issues`: no issue on a page you created or edited.
|
|
198
|
-
5. `get_next_steps`: `receipt.complete` is `true`. While it is `false`, run
|
|
199
|
-
`receipt.gate.nextAction` and read again after each batch; nothing else ends an imported
|
|
200
|
-
site's setup, and an exception is recorded only for a reason that is true. The gate, its bars and the exceptions it accepts are in
|
|
201
|
-
[finish-site.md](references/finish-site.md). Suggestions still in `missing` after that, and
|
|
202
|
-
owner actions, go in your final message by name.
|
|
203
|
-
|
|
204
|
-
"Done" means the loop is clean and the gate reads complete, not that a tool call returned 200.
|
|
205
|
-
`bettercms init` reads the gate again when you exit and prints its numbers per page, so the
|
|
206
|
-
user sees them whatever your last message said.
|
|
1
|
+
---
|
|
2
|
+
name: bettercms
|
|
3
|
+
description: "BetterCMS: build, convert, import, edit, publish and verify BetterCMS sites. Use whenever the user names BetterCMS or its MCP, or the repo has @bettercms-ai/* packages, data-bcms- attributes, bcms-content.json or bcms-rebuild.yml, even when they only say 'make it editable', 'import my site', 'convert this repo', 'add a section', 'fix the schema' or 'publish'. Covers setup, the finish-site workflow, content modeling, components, click-to-edit bindings, Portable Text, media, forms, SEO and launch review. Moving off another CMS: bettercms-migrate. ABM campaigns: bettercms-abm."
|
|
4
|
+
license: MIT
|
|
5
|
+
metadata:
|
|
6
|
+
author: bettercms
|
|
7
|
+
version: "0.3.0"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# BetterCMS
|
|
11
|
+
|
|
12
|
+
The BetterCMS MCP serves its own doctrine, so this skill carries only what the server cannot see:
|
|
13
|
+
your repo's framework wiring, binding attributes, env names, stored value shapes and the traps
|
|
14
|
+
that only show up in code. Read doctrine from the MCP, never from memory:
|
|
15
|
+
|
|
16
|
+
- Schema, sections, variants, publish order: resource `bettercms://playbook/schema` (§1–§14).
|
|
17
|
+
- Content sidebar organisation: resource `bettercms://playbook/structure`.
|
|
18
|
+
- Section patterns (149 worked kit entries by category and edge tag): resource `bettercms://kit`.
|
|
19
|
+
- Guided flows: the `studio` prompt routes to the rest (`convert_site` prompt,
|
|
20
|
+
`build_site` prompt, `componentize_site` prompt, `propose_schema` prompt, `new_page` prompt,
|
|
21
|
+
`new_component` prompt, `new_form` prompt, `seo_optimize` prompt, `import-site` prompt,
|
|
22
|
+
`field-ui` prompt, `edit_layout` prompt for the Global Layout, `generate_landing_pages` prompt
|
|
23
|
+
for page families from data).
|
|
24
|
+
- Import and modelling rule ids: `CM-01`…`CM-83` in the content-modeling standard.
|
|
25
|
+
|
|
26
|
+
## Start here
|
|
27
|
+
|
|
28
|
+
Setting up a project, or asked to "Continue BetterCMS setup"? Read
|
|
29
|
+
[references/getting-started.md](references/getting-started.md) first: it owns the setup phases
|
|
30
|
+
and the resume check. For any other task, read the one reference the table below names.
|
|
31
|
+
|
|
32
|
+
## Connecting (before your first MCP call)
|
|
33
|
+
|
|
34
|
+
Listing tools needs no sign-in; the first tool **call** does.
|
|
35
|
+
|
|
36
|
+
1. **A 401 on the first call is the sign-in, not an error.** The client opens a browser sign-in
|
|
37
|
+
from the `WWW-Authenticate` header. Tell the user to approve it, then retry that same call.
|
|
38
|
+
2. **If `list_projects` lacks the project id you were given, stop and say so.** Consent binds to
|
|
39
|
+
the workspace the dashboard had active; ask the user to re-authenticate in the right one.
|
|
40
|
+
Never continue in whichever project IS listed: that writes into someone else's site.
|
|
41
|
+
3. **Pass `projectId` on every project tool, and never ask the user to re-scope.** A
|
|
42
|
+
workspace-wide connection reaches every project by naming it per call.
|
|
43
|
+
4. **A refusal for access: call `whoami` first.** It names the principal, the workspace, the
|
|
44
|
+
scope (project or workspace) and, where visible, the grants (publish, code and deploy,
|
|
45
|
+
sidebar schema), so you can tell the user which one is missing.
|
|
46
|
+
5. **"Invalid tool parameters" is the client, not BetterCMS.** A client with tool search (Claude
|
|
47
|
+
Code) lists most of the 150 tools by name and loads a schema on demand; a call to a tool whose
|
|
48
|
+
schema it has not loaded is refused before it is sent. Load the tool with the client's tool
|
|
49
|
+
search, every tool the step needs in one search, then make the same call again. Never change
|
|
50
|
+
the arguments because of it. The tools a setup starts with are always loaded.
|
|
51
|
+
6. **Unsure how a feature works: `search_docs` before guessing.** A tool that fails oddly, a
|
|
52
|
+
capability you needed and did not have, or docs that misled you: `give_feedback`, and tell the
|
|
53
|
+
user you sent it.
|
|
54
|
+
|
|
55
|
+
## Invariants
|
|
56
|
+
|
|
57
|
+
These hold on every task. The reference in brackets has the detail and the codes.
|
|
58
|
+
|
|
59
|
+
1. **Confirm the bound project before any write**: §9 of the schema playbook, then `get_project`.
|
|
60
|
+
Its `authoringPreference` defaults to components (recorded by a deploy, a promote or setup)
|
|
61
|
+
and is never asked; the owner can switch it to fields.
|
|
62
|
+
2. **Never create SEO fields** (§5b). Page and entry meta are native columns. [seo.md]
|
|
63
|
+
3. **A page is a list of sections**, never loose top-level blocks, and never a nav, footer or
|
|
64
|
+
modal: chrome is the Layout. A call to action is one `button` field, never a text field
|
|
65
|
+
beside a link field. [components.md, content-modeling.md]
|
|
66
|
+
4. **Nothing is live until it is published, and a page is not its content.** A draft form,
|
|
67
|
+
component or entry renders nothing live. Read `warnings` on every write: `ENTRY_STILL_DRAFT`
|
|
68
|
+
and `ENTRY_SEED_FAILED` mean content did not ship. An answer that leads with `held`, and a
|
|
69
|
+
publish reading `outcome.status: "partial"`, did not reach the site: do the action it names
|
|
70
|
+
before you report it.
|
|
71
|
+
[publishing.md]
|
|
72
|
+
5. **Name the folder system every time you say "folder"**: Content sidebar folders never touch a
|
|
73
|
+
URL, URL page folders are part of the path, media folders organise assets.
|
|
74
|
+
[content-modeling.md]
|
|
75
|
+
6. **Headless projects are built by their host.** Never `deploy_project`, `deploy_to_host` or
|
|
76
|
+
`create_deploy_upload` there, never add `bcms-rebuild.yml`; deploy with
|
|
77
|
+
`npx @bettercms-ai/cli@latest deploy --to <host>`, or push to the repo the host builds.
|
|
78
|
+
Done = `receipt.frontEnd` closed. [getting-started.md]
|
|
79
|
+
7. **Every refusal has a code. Report it; do not retry blind.** The same call returns the same
|
|
80
|
+
code. Change the input or stop.
|
|
81
|
+
8. **Media is served by the backend that owns the asset ids.** `mediaUrl` is `mediaBaseUrl` from
|
|
82
|
+
`get_project`; never hardcode, re-point or re-host media, and never read a bucket or key.
|
|
83
|
+
[frameworks.md]
|
|
84
|
+
9. **Bind the leaf that renders the value, one address per element.** Attribute values ride
|
|
85
|
+
`data-bcms-props`; `data-bcms-kind` declares the container, and the MODEL picks the editor.
|
|
86
|
+
Inside an instance the address is `<instanceId>__overrides.<key>`; chrome uses
|
|
87
|
+
`data-bcms-layout-field`. [bindings.md]
|
|
88
|
+
10. **Declared mode is a switch you flip** with `set_binding_mode` after the stamped build reports
|
|
89
|
+
clean: push, release, report clean, flip, release again. [bindings.md]
|
|
90
|
+
11. **A field is not editable because it exists.** It is editable when its value renders from the
|
|
91
|
+
CMS on a bound leaf and an edit shows in preview and after publish.
|
|
92
|
+
12. **Bulk work runs as code, not as a chain of tool calls.** Propose the mapping and dry-run it
|
|
93
|
+
before a high-volume write; use the MCP for state, targeted fixes and reports.
|
|
94
|
+
13. **A build makes a site live, not editable.** It brings in SEO and meta, media, the brand and
|
|
95
|
+
the models `bcms-content.json` declares. Pages, collections, forms, bindings and components
|
|
96
|
+
are `editor_setup`'s: run it after an import or a rebuild (`get_deploy_status` `editorSetup`
|
|
97
|
+
`never` or `stale`). It also fills missing meta, merges identical components and adopts
|
|
98
|
+
declared bindings when proven; do only what get_next_steps still lists. [getting-started.md]
|
|
99
|
+
|
|
100
|
+
## What you do, and what only the owner does
|
|
101
|
+
|
|
102
|
+
The MCP acts as the signed-in person. Some decisions are theirs by design: no tool makes them,
|
|
103
|
+
and saying you made one is a false report. Name each as an action in your final message.
|
|
104
|
+
|
|
105
|
+
| Only the owner | Where |
|
|
106
|
+
|---|---|
|
|
107
|
+
| Authoring preference and media delivery answers | you ask; `set_authoring_preference`, `set_media_delivery` |
|
|
108
|
+
| Visual Approval of a component, CI (GitHub Actions) validation | dashboard |
|
|
109
|
+
| Approving a generated job or a flagged ABM entry | the user's explicit yes before `approve_ai_job` / `approve_campaign_entries` |
|
|
110
|
+
| Brand colours and typography; URL page folders; unpublishing a form | dashboard |
|
|
111
|
+
| Hosting **Run as a server app**; form integrations; the Turnstile secret | dashboard |
|
|
112
|
+
| `llms.txt` and Markdown twin switches | dashboard, SEO permission |
|
|
113
|
+
| Publishing to production | the user's authorization, then the tools |
|
|
114
|
+
|
|
115
|
+
Secrets never go in a tool call, a `PUBLIC_` variable or a client bundle. A 403
|
|
116
|
+
`SCHEMA_ACCESS_REQUIRED` means the person lacks Admin or Developer access: stop and tell them.
|
|
117
|
+
|
|
118
|
+
## Which reference to read
|
|
119
|
+
|
|
120
|
+
Read one reference per phase. Each is self-contained; a second one is needed only when the task
|
|
121
|
+
crosses into its topic. When this skill is not installed, the MCP serves the same files as
|
|
122
|
+
resources: `bettercms://skill/bettercms` for this file, and each reference under its file stem
|
|
123
|
+
(`bettercms://skill/seo` for seo.md).
|
|
124
|
+
|
|
125
|
+
| Task | Reference | Read when | Keywords |
|
|
126
|
+
|---|---|---|---|
|
|
127
|
+
| Set up or resume a project | [getting-started.md](references/getting-started.md) | first contact, or "Continue BetterCMS setup" | setup, resume, onboarding, connect, import my site, headless, own front end, SDK, CLI |
|
|
128
|
+
| Finish an imported or converted site | [finish-site.md](references/finish-site.md) | a convert or build job; "make it fully editable"; the gap ledger | make it editable, finish, gap ledger, convert |
|
|
129
|
+
| Move content out of another CMS (Cosmic, Contentful, Sanity, Strapi, Prismic, WordPress…) | [external-content.md](references/external-content.md) | a CMS SDK in package.json; `envWarning` on import; pages that render empty without a third-party key | Contentful, Sanity, Strapi, envWarning, missing key, empty pages |
|
|
130
|
+
| Read a source site before modelling it | [detection.md](references/detection.md) | converting from a URL or built HTML; deciding what a band, a repeat or a value is | detect, classify, section, repeat, global, carousel clone, hidden state |
|
|
131
|
+
| Pages vs collections, folders, fields, schema changes | [content-modeling.md](references/content-modeling.md) | modelling a route family; a model write returns 409 | schema, model, collection, field, folder, rename, remove field, listing, filter, locked field |
|
|
132
|
+
| Dock layout: groups, rows, tabs, icons, item names, showIf order | [editor-chrome.md](references/editor-chrome.md) | after any import, convert, componentize or extract (the gate's `dock` row); a `dock-*` rule; the `field-ui` prompt | dock, fieldset, tab, group, itemLabel, showIf, field-ui |
|
|
133
|
+
| A custom input for one field in the dock: when, the user's approval, the contract | [dock-input.md](references/dock-input.md) | `get_next_steps` lists `dock-input-candidate`; a 409 `input_needs_confirmation` | custom input, ui.input, dock input, confirmed, swatch |
|
|
134
|
+
| What the server does and does not check on a write | [write-limits.md](references/write-limits.md) | before relying on a limit; reading a refused write; a bulk load or re-run | validation, maxLength, unique, 400, refused write, dry run, externalKey, upsert, re-run |
|
|
135
|
+
| Plan a site by business type | [site-blueprints.md](references/site-blueprints.md) | the IA of a known site type, with its collections, forms and structured data | new site, IA, portfolio, agency, corporate, SaaS, ecommerce, directory, blog, docs, restaurant, events, course, jobs, real estate, nonprofit, multi-brand |
|
|
136
|
+
| Components, props, variants, component publish codes | [components.md](references/components.md) | creating, swapping, publishing or validating a component | component, prop, variant, sectionType, publish component |
|
|
137
|
+
| Which kit pattern fits a section, and its shape and pitfalls, by category and edge tag | [kit-scenarios.md](references/kit-scenarios.md) | before designing any section's fields or props; a band detection.md classified | kit, pattern, scenario, edge tag, events, locations, calculator, map, chart, docs, team, bento, slots, personalization, localized |
|
|
138
|
+
| One section, source HTML to bound template: hero, feature grid, pricing table, testimonials, FAQ, bento | [worked-examples.md](references/worked-examples.md) | you want the whole path for one section in production shapes | example, hero, pricing, FAQ, testimonial, source to schema |
|
|
139
|
+
| The same for an article entry, navigation in the Global Layout, tabs holding columns | [worked-examples-advanced.md](references/worked-examples-advanced.md) | a collection entry with a body, site chrome, or nested blocks | example, blog post, document body, mega menu, tabs, columns |
|
|
140
|
+
| The modelled section closest to the one you are building: schema, HTML signals, mcp steps, pitfalls | [kit-catalog.md](references/kit-catalog.md) | before designing a section or its props; matching source HTML to a known pattern | kit, catalogue, edge tag, section pattern, bento, localized, personalization, a11y, responsive |
|
|
141
|
+
| Componentize a derived site | [componentize.md](references/componentize.md) | `get_site_composition` shows pages made of fields only | componentize, sections, fields-only, get_componentize_plan, BcmsSections, --sections |
|
|
142
|
+
| Click-to-edit attributes, addresses, declared mode | [bindings.md](references/bindings.md) | `grep -rl "data-bcms-" src` finds files; a value the editor cannot select | data-bcms-field, click to edit, binding report, stega, declared |
|
|
143
|
+
| Animated sites: GSAP, ScrollTrigger, split text, Motion, Lenis, Locomotive, three.js and WebGL, marquees, carousels, Lottie, hydrated islands, and what must stand down in the editor's canvas (`inEditor()`) | [animation.md](references/animation.md) | `package.json` lists `gsap`, `lenis`, `locomotive-scroll`, `framer-motion` or `motion`, `three`, `swiper` or a text splitter; a publish refused with `SPLIT_PATTERN_UNKNOWN` or `ISLAND_PROPS_UNMATCHED`; a `client-only-island` gate exception | animation, GSAP, ScrollTrigger, SplitText, Lenis, Framer Motion, marquee, Swiper, Lottie, island, client:only, data-bcms-split |
|
|
144
|
+
| Wiring, env, hosting modes, media host, snapshots | [frameworks.md](references/frameworks.md) | `package.json` lists an adapter; `bcms-content.json` exists | hosting, headless, env, codegen, types, revalidate, snapshot |
|
|
145
|
+
| Astro adapter | [astro.md](references/astro.md) | the repo has `astro.config.*` | astro.config, Astro, BcmsBlocks, getStaticPaths |
|
|
146
|
+
| Next.js adapter | [next.md](references/next.md) | the repo has `next.config.*` | next.config, Next.js, App Router, ISR, notFound, static export |
|
|
147
|
+
| Nuxt, SvelteKit, React Router, Vite: no adapter | [other-frameworks.md](references/other-frameworks.md) | neither `astro.config.*` nor `next.config.*`; `nuxt.config.*`, `svelte.config.*`, `react-router.config.*` | Nuxt, SvelteKit, React Router, Vite, createClient |
|
|
148
|
+
| Rich text and field types | [portable-text.md](references/portable-text.md) | writing a richtext value; converting HTML or Markdown | rich text, Portable Text, richtext, HTML, Markdown |
|
|
149
|
+
| Brand kit, tokens, fonts, logo, images, icons | [media-and-brand.md](references/media-and-brand.md) | design fidelity, alt text, a logo or favicon change | brand, tokens, fonts, logo, image, alt text, favicon |
|
|
150
|
+
| Connect a vendor with a public API (jobs board, store, CRM, video): declare, approve, call, recipes | [integrations.md](references/integrations.md) | the user names Greenhouse, JobDiva, Shopify, HubSpot, Zoom, Apollo or any API; a 409 `integration_not_approved` | integration, API key, Greenhouse, JobDiva, Shopify, HubSpot, Zoom, Apollo, sync, vendor, token |
|
|
151
|
+
| Forms, menus, accordions, modals, consent | [forms-and-interactions.md](references/forms-and-interactions.md) | attaching or verifying a form; an interactive section | form, submission, Turnstile, modal, accordion, menu |
|
|
152
|
+
| Languages, locale prefixes, translation, hreflang | [localization.md](references/localization.md) | the build serves `/fr`-style prefixes; `locale-unvarianted` in a binding report | language, locale, /fr, translate, hreflang, i18n |
|
|
153
|
+
| SEO and AEO | [seo.md](references/seo.md) | meta, JSON-LD, sitemap, robots, redirects, AI crawlers, `list_seo_issues` | SEO, meta, JSON-LD, schema.org, sitemap, robots, OG image, redirect, 410, llms.txt |
|
|
154
|
+
| Accessibility: alt text, form labels, contrast, the audit codes and the manual checks | [accessibility.md](references/accessibility.md) | writing alt text; building a form; before reporting a site done | accessibility, WCAG, alt text, decorative, label, contrast, captions |
|
|
155
|
+
| Page families from data | [programmatic-seo.md](references/programmatic-seo.md) | a keyword list or CSV should become pages | programmatic SEO, CSV, dataset, landing pages, glossary |
|
|
156
|
+
| Publish, deploy, roll back, reconcile a re-import; add a section to a page or set its spacing | [publishing.md](references/publishing.md) | a release; a code push that conflicts with CMS edits; "add a section here", "more padding on this section"; a write that answers `held` or a publish that reads `partial` | publish, deploy, rollback, sync, webhook, schedule, automation, add section, insertSection, sectionStyle, spacing, padding, margin, held, partial |
|
|
157
|
+
| Read-only launch review | [site-review.md](references/site-review.md) | "is this ready to launch?" without fixing | launch review, audit, is it ready, QA |
|
|
158
|
+
| A/B tests on section variants | [content-experiments.md](references/content-experiments.md) | an experiment plan or readout | A/B test, experiment, variant test |
|
|
159
|
+
| Headless Shopify storefront | [shopify-headless.md](references/shopify-headless.md) | Shopify owns commerce, BetterCMS the editorial | Shopify, Hydrogen, storefront, product |
|
|
160
|
+
|
|
161
|
+
Other sites move into BetterCMS with the `bettercms-migrate` skill; per-account campaign pages
|
|
162
|
+
are the `bettercms-abm` skill.
|
|
163
|
+
|
|
164
|
+
## Context budget
|
|
165
|
+
|
|
166
|
+
A whole-site job outlives one context window. Spend it on the site, not on re-reading.
|
|
167
|
+
|
|
168
|
+
- Start from the receipt: `get_next_steps` returns `receipt.done`, `receipt.missing` and
|
|
169
|
+
`receipt.nextAction`. Plan the session from it, not from re-reading the site.
|
|
170
|
+
- Hold SKILL.md plus only the ONE reference the current phase needs; drop it when the phase ends.
|
|
171
|
+
- Ask the MCP for summaries before reading files: `get_site_composition`, `get_binding_report`
|
|
172
|
+
and `get_next_steps` answer "what is left" in a few hundred tokens, where built HTML or a whole
|
|
173
|
+
repo costs tens of thousands.
|
|
174
|
+
- Run bulk edits through the codemod (`npx @bettercms-ai/convert`), not file-by-file hand edits
|
|
175
|
+
in context; read its receipt, not the diff.
|
|
176
|
+
- Keep the gap ledger in `.bettercms/ledger.json` in the repo (shape in finish-site.md) and
|
|
177
|
+
re-read it after a reset instead of carrying it in chat.
|
|
178
|
+
- Where your agent supports subagents, fan out per-route verification and have each return only
|
|
179
|
+
its verdict and the failing evidence.
|
|
180
|
+
- Pass the `projectId` you already have; never re-list projects to find it again.
|
|
181
|
+
- After a reset, say "Continue BetterCMS setup": the resume check rebuilds state from the MCP and
|
|
182
|
+
the ledger.
|
|
183
|
+
|
|
184
|
+
## Verify loop (after every change, before you say "done")
|
|
185
|
+
|
|
186
|
+
Stop at the first step that is not clean, fix, then restart. A report that does not exist yet is
|
|
187
|
+
"not yet generated", which is not the same as dirty; say which.
|
|
188
|
+
|
|
189
|
+
1. **Fetch the live URL**, cache-busted: a 200 whose body contains copy you just published. The
|
|
190
|
+
steps below read the control plane, and all of them can be green on a site that answers 404.
|
|
191
|
+
2. `get_binding_report` for every route you touched: `unaddressable` under 2%, and, where the
|
|
192
|
+
source declares its bindings, `coverage.pending` empty and `mode: "declared"`. `refreshReason: "never-generated"` means no BetterCMS
|
|
193
|
+
release wrote one (on headless none ever will, so step 1 is the proof); `"outdated"` means
|
|
194
|
+
the next release rewrites it.
|
|
195
|
+
3. `get_site_composition`: every page you touched is made of sections, with the intended
|
|
196
|
+
components.
|
|
197
|
+
4. `list_seo_issues`: no issue on a page you created or edited.
|
|
198
|
+
5. `get_next_steps`: `receipt.complete` is `true`. While it is `false`, run
|
|
199
|
+
`receipt.gate.nextAction` and read again after each batch; nothing else ends an imported
|
|
200
|
+
site's setup, and an exception is recorded only for a reason that is true. The gate, its bars and the exceptions it accepts are in
|
|
201
|
+
[finish-site.md](references/finish-site.md). Suggestions still in `missing` after that, and
|
|
202
|
+
owner actions, go in your final message by name.
|
|
203
|
+
|
|
204
|
+
"Done" means the loop is clean and the gate reads complete, not that a tool call returned 200.
|
|
205
|
+
`bettercms init` reads the gate again when you exit and prints its numbers per page, so the
|
|
206
|
+
user sees them whatever your last message said.
|