@bettercms-ai/mcp 0.82.0 → 0.83.0
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/dist/index.js +14 -9
- package/dist/index.js.map +1 -1
- package/dist/skills/bettercms/references/frameworks.md +3 -0
- package/dist/skills/bettercms/references/getting-started.md +24 -9
- package/dist/skills/bettercms/references/next.md +10 -7
- package/dist/skills/bettercms/references/other-frameworks.md +21 -4
- package/package.json +2 -2
|
@@ -45,6 +45,9 @@ found itself. So: switch Hosting first (ask the owner), then ship the build, the
|
|
|
45
45
|
| `@bettercms-ai/astro` | `PUBLIC_BCMS_API_URL`, `PUBLIC_BCMS_WORKSPACE`, `PUBLIC_BCMS_PROJECT_ID` | Where reads go |
|
|
46
46
|
| `@bettercms-ai/astro` | `PUBLIC_BCMS_MEDIA_URL`, `PUBLIC_BCMS_STUDIO_URL` | Media host, editor origin |
|
|
47
47
|
| `@bettercms-ai/astro` | `BCMS_API_KEY`, `BCMS_DRAFT_SECRET` | Server-only key; draft cookie signing |
|
|
48
|
+
| `@bettercms-ai/react` | `VITE_BCMS_API_URL`, `VITE_BCMS_WORKSPACE`, `VITE_BCMS_PROJECT_ID` | Where reads go (no key, no secret: a browser app) |
|
|
49
|
+
| `@bettercms-ai/sveltekit` | `PUBLIC_BCMS_API_URL`, `PUBLIC_BCMS_WORKSPACE`, `PUBLIC_BCMS_PROJECT_ID`; `BCMS_DRAFT_SECRET` | Where reads go; draft cookie signing |
|
|
50
|
+
| `@bettercms-ai/nuxt` | `NUXT_PUBLIC_BCMS_API_URL`, `NUXT_PUBLIC_BCMS_WORKSPACE`, `NUXT_PUBLIC_BCMS_PROJECT_ID`; `BCMS_DRAFT_SECRET` | Where reads go; draft cookie signing |
|
|
48
51
|
| `@bettercms-ai/next` (snapshot bin) | `BETTERCMS_API_URL`, `BETTERCMS_API_KEY`, `BETTERCMS_WORKSPACE` | Pull `bcms-content.json` |
|
|
49
52
|
| `@bettercms-ai/next` | `BETTERCMS_PREVIEW=1` | Read live instead of the snapshot in a preview build |
|
|
50
53
|
| `@bettercms-ai/codegen` | `BETTERCMS_API_URL`, `BETTERCMS_API_KEY` | Fetch models for typegen |
|
|
@@ -121,21 +121,36 @@ Check: the deployed site passes the numbers below on every route.
|
|
|
121
121
|
## A headless project (its own front end)
|
|
122
122
|
|
|
123
123
|
`get_project` says `hostingMode: "headless"`: BetterCMS never builds this site, its own host does.
|
|
124
|
-
Done is `receipt.frontEnd` closed in get_next_steps:
|
|
125
|
-
|
|
124
|
+
Done is `receipt.frontEnd` closed AND `receipt.gate` complete in get_next_steps: BetterCMS derived
|
|
125
|
+
the owner's pages, their code reads the content, the front end has its site URL and rebuilds on
|
|
126
|
+
publish. Work the rows in order; never `deploy_project` or `deploy_to_host`.
|
|
126
127
|
|
|
127
128
|
1. **Launched by `bettercms init`** (`--agent claude|codex|opencode|cursor|gemini`): you run in the
|
|
128
|
-
front end
|
|
129
|
-
|
|
130
|
-
|
|
129
|
+
owner's own front end, already connected. Do not ask to be restarted. **Their code, design and
|
|
130
|
+
copy ARE the site:** keep every component, route, class, style and asset; never redesign a page,
|
|
131
|
+
rebuild one from scratch or swap their components for new ones. A starter is only ever the
|
|
132
|
+
starting point when the owner chose one (`init --framework`).
|
|
133
|
+
2. **Derive** (`derive` row). `npx @bettercms-ai/cli@latest derive` in the front end's folder builds
|
|
134
|
+
the site, renders every page as a visitor sees it and sends the pages to BetterCMS, which derives
|
|
135
|
+
their pages, fields and today's copy exactly as from a build it made. init runs it first; run it
|
|
136
|
+
yourself while the row is open. Never model those pages again.
|
|
137
|
+
3. **Convert in place** (`receipt.gate`, the same gate as any built site). `get_conversion_brief
|
|
138
|
+
{ complete: true }`, the convert codemod over this folder (its command is in
|
|
139
|
+
`bettercms://playbook/schema` §13), then `submit_conversion_receipt` with the receipt it wrote:
|
|
140
|
+
each literal becomes a read of its field with the markup byte-identical. Bind what it leaves pending by hand the same way. Then
|
|
141
|
+
start the build script with it, `"build": "bettercms pull-content && next build"`
|
|
142
|
+
(`@bettercms-ai/cli` a devDependency; not a `prebuild` hook, which Yarn and pnpm skip): the
|
|
143
|
+
converted pages read `bcms-content/*.json`, which only that step writes on the host's build.
|
|
144
|
+
4. **Wire and read.** `.env` gets `BCMS_API_URL`, `BCMS_WORKSPACE` and `BCMS_PROJECT_ID` (from
|
|
131
145
|
`get_project`); published content needs no key. A starter whose config reads a key gets one
|
|
132
146
|
from `create_delivery_key` (`scope: "published"`), written straight into `.env`, never into
|
|
133
147
|
chat or a commit. Run the app and load a page: its first read closes `read`.
|
|
134
|
-
|
|
148
|
+
5. **Deploy.** `npx @bettercms-ai/cli@latest deploy --to vercel|netlify|cloudflare` from the
|
|
135
149
|
folder: the host's own sign-in, the `BCMS_*` variables set there, and the rebuild hook
|
|
136
150
|
registered (`publish-hook`). A front end that revalidates instead: `set_front_end
|
|
137
|
-
{ revalidation }`.
|
|
138
|
-
|
|
151
|
+
{ revalidation }`. Then `derive` again, so the gate measures what ships: on headless, every
|
|
152
|
+
gate fix that says rebuild means deploy, then derive.
|
|
153
|
+
6. **Open it from BetterCMS.** `set_front_end { siteUrl, framework }` with the deployed URL
|
|
139
154
|
(`preview`); editors' "Preview on site" opens drafts there.
|
|
140
|
-
|
|
155
|
+
7. **Publish**, then get_next_steps until `receipt.complete` is true. Schema and content work is
|
|
141
156
|
the same as on any project ([content-modeling.md](content-modeling.md)).
|
|
@@ -28,10 +28,10 @@ Nothing is mounted automatically. Add the routes:
|
|
|
28
28
|
|
|
29
29
|
## Revalidation route
|
|
30
30
|
|
|
31
|
-
`createRevalidateRoute(
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
`
|
|
31
|
+
`createRevalidateRoute()` → export `POST`. It verifies `X-BetterCMS-Signature` against the raw
|
|
32
|
+
body with `secret`, else `BCMS_REVALIDATE_SECRET` (the project's revalidation secret from the
|
|
33
|
+
dashboard), then revalidates every tag (`revalidateTag(tag, "max")`) and every page path
|
|
34
|
+
(`revalidatePath`) the publish changed. Tag your reads with the backend's tag strings
|
|
35
35
|
([frameworks.md](frameworks.md) Revalidation).
|
|
36
36
|
|
|
37
37
|
## Rendering
|
|
@@ -164,8 +164,11 @@ Pages Router the page passes on the prop it got: `<HomeView bcmsSections={bcmsSe
|
|
|
164
164
|
|
|
165
165
|
## Static export (`output: "export"`)
|
|
166
166
|
|
|
167
|
-
-
|
|
168
|
-
`
|
|
167
|
+
- Pull the content before `next build`, every build: `"build": "bettercms pull-content && next build"`
|
|
168
|
+
(what `bettercms init` writes; keyless, it reads the project's published content).
|
|
169
|
+
`bettercms-snapshot` (from `BETTERCMS_API_URL`, `BETTERCMS_API_KEY`, `BETTERCMS_WORKSPACE`) does the
|
|
170
|
+
same with a key. Either writes `bcms-content.json`, and `createBetterCMS()` with no arguments reads
|
|
171
|
+
its workspace and project from it (after `NEXT_PUBLIC_BCMS_*`).
|
|
169
172
|
- Without the snapshot the reads throw `SNAPSHOT_MISSING`. Why it throws instead of fetching:
|
|
170
173
|
a live fetch would turn pages into dynamic routes, and a static export silently leaves them out
|
|
171
174
|
of `out/`.
|
|
@@ -180,7 +183,7 @@ Pages Router the page passes on the prop it got: `<HomeView bcmsSections={bcmsSe
|
|
|
180
183
|
|
|
181
184
|
| Symptom | Cause | Rule |
|
|
182
185
|
|---|---|---|
|
|
183
|
-
| Empty `out/` after `next build` | No snapshot | Run `bettercms-
|
|
186
|
+
| Empty `out/` after `next build` | No snapshot | Run `bettercms pull-content` first |
|
|
184
187
|
| Page never updates after publish | Read tags do not match backend tags | Use `bcms:{workspace}:…` tags |
|
|
185
188
|
| Component instance renders nothing | `components` not passed | `readComponents()` into `BcmsBlocks` |
|
|
186
189
|
| Canonical missing or wrong only on the self-hosted site | `buildMetadata` without `location`, and no `BETTERCMS_SITE_URL` or a prefixed route | Pass `{ siteUrl, path }` |
|
|
@@ -5,10 +5,27 @@ description: "Reading BetterCMS content from Nuxt, SvelteKit, React Router or Vi
|
|
|
5
5
|
|
|
6
6
|
# Other frameworks
|
|
7
7
|
|
|
8
|
-
Read this when the repo has neither `astro.config.*` nor `next.config.*`.
|
|
9
|
-
adapters;
|
|
10
|
-
same one
|
|
11
|
-
tags) are in [frameworks.md](frameworks.md).
|
|
8
|
+
Read this when the repo has neither `astro.config.*` nor `next.config.*`. React (Vite), SvelteKit
|
|
9
|
+
and Nuxt have adapters (§0); anything else reads through the framework-agnostic core in
|
|
10
|
+
`@bettercms-ai/sdk`, the same one every adapter wraps. Shared rules (hosting modes, value shapes,
|
|
11
|
+
media host, revalidation tags) are in [frameworks.md](frameworks.md).
|
|
12
|
+
|
|
13
|
+
## 0. The adapters
|
|
14
|
+
|
|
15
|
+
| Repo has | Install | Settings | Sections | Drafts |
|
|
16
|
+
|---|---|---|---|---|
|
|
17
|
+
| `vite.config.*` + React | `@bettercms-ai/react` | `<BcmsProvider env={import.meta.env}>`, `VITE_BCMS_*` | `<BcmsBlocks blocks={page.blocks}>` (Next's markup) | the editor's `/api/draft` link, no server; the host rewrites it to the app |
|
|
18
|
+
| `svelte.config.*` (SvelteKit) | `@bettercms-ai/sveltekit` | `createBcms({ env: { ...publicEnv, ...privateEnv } })`, `PUBLIC_BCMS_*` | `bcms.sections(slug, fetch)` in `load`, then `<div use:bcmsSections={data.sections}>{@html sectionsMarkup(data.sections)}</div>` | `src/routes/api/draft/+server.ts`: `GET = ({ request }) => bcms.draftEnable(request)`; `await bcms.client(request)` reads drafts |
|
|
19
|
+
| `nuxt.config.*` | `@bettercms-ai/nuxt` | `createBcms({ env: process.env })` in `server/utils`, `NUXT_PUBLIC_BCMS_*` | a server route returning `bcms.sections(slug)`, then `<div v-bcms-sections v-html="sectionsMarkup(data)">` | `server/routes/api/draft.get.ts`: `bcms.draftEnable(toWebRequest(e))` |
|
|
20
|
+
|
|
21
|
+
- SvelteKit and Nuxt sections are server-rendered by BetterCMS (the hosted renderer's markup, a
|
|
22
|
+
stylesheet scoped to `[data-bcms-rendered="platform"]`, and the form, slider and tab scripts):
|
|
23
|
+
never rebuild them as components, and never paste their HTML into the repo. Field copy outside
|
|
24
|
+
the sections is still read with the client and bound with `data-bcms-field`
|
|
25
|
+
([bindings.md](bindings.md)).
|
|
26
|
+
- The sections are the PUBLISHED page; draft mode switches the client, not the fragment.
|
|
27
|
+
- Set `BCMS_PROJECT_ID` under the framework's prefix: sections and keyless reads are addressed to it.
|
|
28
|
+
- `BCMS_DRAFT_SECRET` (server-only) signs the draft cookie on SvelteKit and Nuxt; a React SPA has none.
|
|
12
29
|
|
|
13
30
|
## 1. The client
|
|
14
31
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bettercms-ai/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.83.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "BetterCMS MCP server — schema, content, forms + components authoring tools over the Management API, authed via OAuth device-code.",
|
|
6
6
|
"bin": {
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@bettercms-ai/device-auth": "^0.2.0",
|
|
35
|
-
"@bettercms-ai/sdk": "^1.
|
|
35
|
+
"@bettercms-ai/sdk": "^1.35.0",
|
|
36
36
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
37
37
|
"zod": "^4.3.6"
|
|
38
38
|
},
|