@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.
Files changed (40) hide show
  1. package/README.md +86 -86
  2. package/SKILL.md +160 -160
  3. package/dist/index.js +38 -9
  4. package/dist/index.js.map +1 -1
  5. package/dist/kit-catalog.json +1509 -1509
  6. package/dist/skills/bettercms/SKILL.md +206 -206
  7. package/dist/skills/bettercms/references/accessibility.md +171 -171
  8. package/dist/skills/bettercms/references/animation.md +296 -296
  9. package/dist/skills/bettercms/references/astro.md +148 -148
  10. package/dist/skills/bettercms/references/bindings.md +366 -366
  11. package/dist/skills/bettercms/references/componentize.md +185 -185
  12. package/dist/skills/bettercms/references/components.md +415 -415
  13. package/dist/skills/bettercms/references/content-experiments.md +62 -62
  14. package/dist/skills/bettercms/references/content-modeling.md +382 -382
  15. package/dist/skills/bettercms/references/detection.md +465 -465
  16. package/dist/skills/bettercms/references/dock-input.md +121 -121
  17. package/dist/skills/bettercms/references/editor-chrome.md +92 -92
  18. package/dist/skills/bettercms/references/external-content.md +78 -78
  19. package/dist/skills/bettercms/references/finish-site.md +377 -377
  20. package/dist/skills/bettercms/references/forms-and-interactions.md +245 -245
  21. package/dist/skills/bettercms/references/frameworks.md +159 -159
  22. package/dist/skills/bettercms/references/getting-started.md +156 -156
  23. package/dist/skills/bettercms/references/integrations.md +364 -364
  24. package/dist/skills/bettercms/references/kit-catalog.md +3259 -3259
  25. package/dist/skills/bettercms/references/kit-scenarios.md +712 -712
  26. package/dist/skills/bettercms/references/localization.md +85 -85
  27. package/dist/skills/bettercms/references/media-and-brand.md +181 -181
  28. package/dist/skills/bettercms/references/next.md +189 -189
  29. package/dist/skills/bettercms/references/other-frameworks.md +85 -85
  30. package/dist/skills/bettercms/references/portable-text.md +213 -213
  31. package/dist/skills/bettercms/references/programmatic-seo.md +98 -98
  32. package/dist/skills/bettercms/references/publishing.md +289 -289
  33. package/dist/skills/bettercms/references/seo.md +357 -357
  34. package/dist/skills/bettercms/references/shopify-headless.md +52 -52
  35. package/dist/skills/bettercms/references/site-blueprints.md +895 -895
  36. package/dist/skills/bettercms/references/site-review.md +74 -74
  37. package/dist/skills/bettercms/references/worked-examples-advanced.md +509 -509
  38. package/dist/skills/bettercms/references/worked-examples.md +885 -885
  39. package/dist/skills/bettercms/references/write-limits.md +217 -217
  40. package/package.json +1 -1
@@ -1,148 +1,148 @@
1
- ---
2
- title: "Astro adapter"
3
- description: "The @bettercms-ai/astro integration: options and env precedence, draft preview, shipped components, bindings and Astro-specific traps."
4
- ---
5
-
6
- # @bettercms-ai/astro
7
-
8
- Read this when the repo has `astro.config.*`. Shared rules (hosting modes, env map, tags, value
9
- shapes) are in [frameworks.md](frameworks.md).
10
-
11
- ## Integration
12
-
13
- Add `bettercms()` to `integrations` in `astro.config.*`. It:
14
-
15
- - adds the `@bettercms-ai/astro/middleware` middleware (order `pre`);
16
- - injects `/api/bcms/draft/enable` and `/api/bcms/draft/disable`;
17
- - sets a signed `bcms-draft` cookie when draft mode is enabled.
18
-
19
- Options win over env, env wins over the snapshot: `apiUrl` → `PUBLIC_BCMS_API_URL` → snapshot,
20
- `workspace` → `PUBLIC_BCMS_WORKSPACE` → snapshot, `projectId` → `PUBLIC_BCMS_PROJECT_ID`,
21
- `mediaUrl` → `PUBLIC_BCMS_MEDIA_URL` → the production CDN, `studioUrl` →
22
- `PUBLIC_BCMS_STUDIO_URL` (no default).
23
-
24
- `draft` defaults to `true`, which injects two ON-DEMAND routes (`/api/bcms/draft/{enable,disable}`).
25
- A static build with no server adapter then fails with `NoAdapterInstalled`. On a static site pass
26
- `bettercms({ draft: false })`; draft preview needs an adapter AND the Hosting page set to Run as a
27
- server app (see Hosting modes).
28
-
29
- `astro.config.*` runs before Astro loads `.env`, so `PUBLIC_BCMS_*` is empty there on a local
30
- build. Pass `apiUrl` and `workspace` as options, or let the snapshot supply them.
31
-
32
- ## Draft preview
33
-
34
- - Set `BCMS_DRAFT_SECRET` on the server. Without it `/api/bcms/draft/enable` answers 500.
35
- - The draft routes run on request, so the site needs an on-demand adapter (node, vercel, netlify,
36
- cloudflare). A fully static build serves the published snapshot only.
37
-
38
- ## Components shipped
39
-
40
- | Import | Use |
41
- |---|---|
42
- | `@bettercms-ai/astro/components/BcmsBlocks.astro` | Server render of a block tree. Pass `components` or instances render nothing |
43
- | `@bettercms-ai/astro/components/BcmsSections.astro` | The page's own sections as named slots, drawn in the CMS page's order (below) |
44
- | `@bettercms-ai/astro/components/BcmsLiveBlocks.astro` | Same tree as a hydrated island that follows the editor's draft bridge |
45
- | `@bettercms-ai/astro/components/BcmsField.astro` | `path`, `kind` (`richtext`/`image`), `as`; emits `data-bcms-field` + `data-bcms-kind` on its single child element, with no wrapper ([animation.md](animation.md) §10) |
46
- | `@bettercms-ai/astro/components/BcmsButton.astro` | A `button` field: `path`, `value`, `class`. One `<a>` with the label bound, the href in `data-bcms-props` and `data-variant` / `data-size`. Style only the looks the site has ([components.md](components.md) §5); renders nothing without a label |
47
- | `@bettercms-ai/astro/components/BcmsForm.astro` | Renders a delivered form and submits it ([forms-and-interactions.md](forms-and-interactions.md)) |
48
-
49
- `BcmsLiveBlocks` rules:
50
-
51
- - It needs a React-compatible renderer: add `preact({ compat: true })` next to `bettercms()`.
52
- - Its CSS class names differ from `BcmsBlocks`. Swapping one for the other unstyles a page unless
53
- your stylesheet covers both spellings.
54
-
55
- ## Sections in the CMS order
56
-
57
- A page whose sections are written in its `.astro` file follows the CMS page's block list through
58
- `<BcmsSections>`. `bettercms init` writes this wrap (`npx @bettercms-ai/convert --sections`);
59
- write it by hand for a page the codemod refused ([componentize.md](componentize.md) §5):
60
-
61
- ```astro
62
- ---
63
- import BcmsSections from "@bettercms-ai/astro/components/BcmsSections.astro";
64
- ---
65
- <Layout>
66
- <BcmsSections page="home">
67
- <Fragment slot="hero"><Hero title={title} /></Fragment>
68
- <Fragment slot="code:sec1"><LogoStrip /></Fragment>
69
- <Fragment slot="pricing">{plans.length > 0 && <Pricing plans={plans} />}</Fragment>
70
- </BcmsSections>
71
- </Layout>
72
- ```
73
-
74
- - `page` is the CMS page's slug. Each section is one `<Fragment slot="…">` around markup you do
75
- not change. Anything with its own `slot="…"` (it targets the layout) stays outside.
76
- - A slot is named by its placement's bind: the family of the section's first bound field
77
- (`pricing-title` → `pricing`), which is the `bind` on the page's `component` block.
78
- - A block bound to a slot renders it at the block's position. `data-bcms-block`, `data-bcms-style`
79
- and the block's style go on the section's own root element; no element is added, so the stamp
80
- never comes between a parent and a child a selector or an animation names
81
- ([animation.md](animation.md) §10). A slot that renders several roots, or an island, is stamped
82
- on a box: `display:contents` while its block has no style, one `display:flow-root` box once it
83
- has. Give it one root element where the layout must not gain a box.
84
- - A section added in the editor (a block with no bind) is drawn by `BcmsBlocks`, which
85
- `BcmsSections` imports itself: nothing to pass, and it builds whether or not `bettercms()` is
86
- registered on that build (a config that adds it only with credentials still draws the section).
87
- - A slot no block names: `code:<bind>` always renders where it is written. A bare `<bind>` does
88
- too until the list names one of the page's slots; from then on it is a removed section. Write
89
- a slot bare only when the page already places that bind (`get_page`), otherwise `code:`.
90
- - No snapshot (a local build, the API down): every slot renders in source order, untouched.
91
-
92
- **A page that only draws a view.** Where the page file is a shell (`<HomeView locale="en" />`,
93
- alone or inside its layout) the sections are written in the view, and `--sections` wraps them
94
- there: it follows the import (relative, or a `paths` alias the repository's own tsconfig or
95
- jsconfig declares, index files included) up to three components down, to the first file that
96
- writes two or more sections or writes its run inside a layout. One view often serves several
97
- pages (`/` and `/fr`), so the view cannot name the page. Each page hands it down, and the view
98
- reads it:
99
-
100
- ```astro
101
- <!-- src/pages/fr/index.astro -->
102
- <HomeView locale="fr" bcmsPage="fr" />
103
-
104
- <!-- src/views/HomeView.astro: `bcmsPage?: string` joins its Props -->
105
- <MainLayout>
106
- <BcmsSections page={Astro.props.bcmsPage ?? ""}>
107
- <Fragment slot="hero"><HeroSection title={copy.hero.title} /></Fragment>
108
- …
109
- </BcmsSections>
110
- </MainLayout>
111
- ```
112
-
113
- Each page then follows its own CMS page's list through the one set of slots. A route that hands
114
- the view no page (the CMS has none for it yet) renders the source order. A slot is bare only
115
- when every page drawing the view places that bind. A dynamic route's view (`blog/[id].astro` →
116
- `BlogPostView`) is wrapped the same way with `template`. Write it by hand in this shape when the
117
- codemod refuses the view ([componentize.md](componentize.md) §5).
118
- - The list is the published snapshot's, or the draft's when the Visual Editor frames a
119
- server-rendered page (`prerender = false`). `blocks={…}` gives it yourself.
120
-
121
- Check: build, then view source. `<!--bcms-sections:start page="home"-->` precedes the sections,
122
- and each placed section's root carries `data-bcms-block` and `data-bcms-style`.
123
-
124
- ## Bindings
125
-
126
- A section root your own code renders spreads `sectionRootAttrs(block)` from `@bettercms-ai/astro`
127
- (`data-bcms-block`, `data-bcms-style` and the block's style), so the editor can move it and offer
128
- its spacing handles ([components.md](components.md) §5). It adds `data-bcms-hide` when `style.hideOn` is set: put `RESPONSIVE_CSS` (exported here) in your global CSS.
129
-
130
- `<BcmsBlocks>` does not render a block outside its `window`, read against the `now` prop (default:
131
- render time). Pass `showScheduled` on a draft preview to draw it, marked `data-bcms-window`
132
- ([publishing.md](publishing.md) §6).
133
-
134
- `bind` and `bindProps` from `@bettercms-ai/astro/bindings` produce the same attributes as the Next
135
- helpers. Use them inside component instances so addresses resolve to the instance
136
- ([bindings.md](bindings.md) §3).
137
-
138
- ## Traps
139
-
140
- | Symptom | Cause | Rule |
141
- |---|---|---|
142
- | Resized images 404 on a non-production site | `mediaUrl` still the production default | Set `PUBLIC_BCMS_MEDIA_URL` to that rung's API origin |
143
- | Resized images still on the CDN after moving media | `mediaUrl` not changed | Set it to `mediaBaseUrl` from `get_project` |
144
- | Component instances empty | `components` prop missing | Pass definitions to `BcmsBlocks` |
145
- | A code section vanished after a build | Its slot is bare and the page's block list does not place its bind | Name it `code:<bind>`, or place the bind on the page |
146
- | Build fails on `bettercms:config` | A page imports `BcmsSearch` or the virtual module on a build where `bettercms()` is not registered | Register it unconditionally. `BcmsSections`, `BcmsBlocks`, `BcmsImage` and `BcmsForm` need no integration |
147
- | Draft link 500 | `BCMS_DRAFT_SECRET` unset | Set it on the server env, redeploy |
148
- | `ReferenceError: X is not defined` from a `[slug].astro` route | `getStaticPaths()` reads a `const` declared in the frontmatter; Astro runs it in its own scope, before the page, seeing only imports | Declare the client or reader call inside `getStaticPaths`, or import it from a module |
1
+ ---
2
+ title: "Astro adapter"
3
+ description: "The @bettercms-ai/astro integration: options and env precedence, draft preview, shipped components, bindings and Astro-specific traps."
4
+ ---
5
+
6
+ # @bettercms-ai/astro
7
+
8
+ Read this when the repo has `astro.config.*`. Shared rules (hosting modes, env map, tags, value
9
+ shapes) are in [frameworks.md](frameworks.md).
10
+
11
+ ## Integration
12
+
13
+ Add `bettercms()` to `integrations` in `astro.config.*`. It:
14
+
15
+ - adds the `@bettercms-ai/astro/middleware` middleware (order `pre`);
16
+ - injects `/api/bcms/draft/enable` and `/api/bcms/draft/disable`;
17
+ - sets a signed `bcms-draft` cookie when draft mode is enabled.
18
+
19
+ Options win over env, env wins over the snapshot: `apiUrl` → `PUBLIC_BCMS_API_URL` → snapshot,
20
+ `workspace` → `PUBLIC_BCMS_WORKSPACE` → snapshot, `projectId` → `PUBLIC_BCMS_PROJECT_ID`,
21
+ `mediaUrl` → `PUBLIC_BCMS_MEDIA_URL` → the production CDN, `studioUrl` →
22
+ `PUBLIC_BCMS_STUDIO_URL` (no default).
23
+
24
+ `draft` defaults to `true`, which injects two ON-DEMAND routes (`/api/bcms/draft/{enable,disable}`).
25
+ A static build with no server adapter then fails with `NoAdapterInstalled`. On a static site pass
26
+ `bettercms({ draft: false })`; draft preview needs an adapter AND the Hosting page set to Run as a
27
+ server app (see Hosting modes).
28
+
29
+ `astro.config.*` runs before Astro loads `.env`, so `PUBLIC_BCMS_*` is empty there on a local
30
+ build. Pass `apiUrl` and `workspace` as options, or let the snapshot supply them.
31
+
32
+ ## Draft preview
33
+
34
+ - Set `BCMS_DRAFT_SECRET` on the server. Without it `/api/bcms/draft/enable` answers 500.
35
+ - The draft routes run on request, so the site needs an on-demand adapter (node, vercel, netlify,
36
+ cloudflare). A fully static build serves the published snapshot only.
37
+
38
+ ## Components shipped
39
+
40
+ | Import | Use |
41
+ |---|---|
42
+ | `@bettercms-ai/astro/components/BcmsBlocks.astro` | Server render of a block tree. Pass `components` or instances render nothing |
43
+ | `@bettercms-ai/astro/components/BcmsSections.astro` | The page's own sections as named slots, drawn in the CMS page's order (below) |
44
+ | `@bettercms-ai/astro/components/BcmsLiveBlocks.astro` | Same tree as a hydrated island that follows the editor's draft bridge |
45
+ | `@bettercms-ai/astro/components/BcmsField.astro` | `path`, `kind` (`richtext`/`image`), `as`; emits `data-bcms-field` + `data-bcms-kind` on its single child element, with no wrapper ([animation.md](animation.md) §10) |
46
+ | `@bettercms-ai/astro/components/BcmsButton.astro` | A `button` field: `path`, `value`, `class`. One `<a>` with the label bound, the href in `data-bcms-props` and `data-variant` / `data-size`. Style only the looks the site has ([components.md](components.md) §5); renders nothing without a label |
47
+ | `@bettercms-ai/astro/components/BcmsForm.astro` | Renders a delivered form and submits it ([forms-and-interactions.md](forms-and-interactions.md)) |
48
+
49
+ `BcmsLiveBlocks` rules:
50
+
51
+ - It needs a React-compatible renderer: add `preact({ compat: true })` next to `bettercms()`.
52
+ - Its CSS class names differ from `BcmsBlocks`. Swapping one for the other unstyles a page unless
53
+ your stylesheet covers both spellings.
54
+
55
+ ## Sections in the CMS order
56
+
57
+ A page whose sections are written in its `.astro` file follows the CMS page's block list through
58
+ `<BcmsSections>`. `bettercms init` writes this wrap (`npx @bettercms-ai/convert --sections`);
59
+ write it by hand for a page the codemod refused ([componentize.md](componentize.md) §5):
60
+
61
+ ```astro
62
+ ---
63
+ import BcmsSections from "@bettercms-ai/astro/components/BcmsSections.astro";
64
+ ---
65
+ <Layout>
66
+ <BcmsSections page="home">
67
+ <Fragment slot="hero"><Hero title={title} /></Fragment>
68
+ <Fragment slot="code:sec1"><LogoStrip /></Fragment>
69
+ <Fragment slot="pricing">{plans.length > 0 && <Pricing plans={plans} />}</Fragment>
70
+ </BcmsSections>
71
+ </Layout>
72
+ ```
73
+
74
+ - `page` is the CMS page's slug. Each section is one `<Fragment slot="…">` around markup you do
75
+ not change. Anything with its own `slot="…"` (it targets the layout) stays outside.
76
+ - A slot is named by its placement's bind: the family of the section's first bound field
77
+ (`pricing-title` → `pricing`), which is the `bind` on the page's `component` block.
78
+ - A block bound to a slot renders it at the block's position. `data-bcms-block`, `data-bcms-style`
79
+ and the block's style go on the section's own root element; no element is added, so the stamp
80
+ never comes between a parent and a child a selector or an animation names
81
+ ([animation.md](animation.md) §10). A slot that renders several roots, or an island, is stamped
82
+ on a box: `display:contents` while its block has no style, one `display:flow-root` box once it
83
+ has. Give it one root element where the layout must not gain a box.
84
+ - A section added in the editor (a block with no bind) is drawn by `BcmsBlocks`, which
85
+ `BcmsSections` imports itself: nothing to pass, and it builds whether or not `bettercms()` is
86
+ registered on that build (a config that adds it only with credentials still draws the section).
87
+ - A slot no block names: `code:<bind>` always renders where it is written. A bare `<bind>` does
88
+ too until the list names one of the page's slots; from then on it is a removed section. Write
89
+ a slot bare only when the page already places that bind (`get_page`), otherwise `code:`.
90
+ - No snapshot (a local build, the API down): every slot renders in source order, untouched.
91
+
92
+ **A page that only draws a view.** Where the page file is a shell (`<HomeView locale="en" />`,
93
+ alone or inside its layout) the sections are written in the view, and `--sections` wraps them
94
+ there: it follows the import (relative, or a `paths` alias the repository's own tsconfig or
95
+ jsconfig declares, index files included) up to three components down, to the first file that
96
+ writes two or more sections or writes its run inside a layout. One view often serves several
97
+ pages (`/` and `/fr`), so the view cannot name the page. Each page hands it down, and the view
98
+ reads it:
99
+
100
+ ```astro
101
+ <!-- src/pages/fr/index.astro -->
102
+ <HomeView locale="fr" bcmsPage="fr" />
103
+
104
+ <!-- src/views/HomeView.astro: `bcmsPage?: string` joins its Props -->
105
+ <MainLayout>
106
+ <BcmsSections page={Astro.props.bcmsPage ?? ""}>
107
+ <Fragment slot="hero"><HeroSection title={copy.hero.title} /></Fragment>
108
+ …
109
+ </BcmsSections>
110
+ </MainLayout>
111
+ ```
112
+
113
+ Each page then follows its own CMS page's list through the one set of slots. A route that hands
114
+ the view no page (the CMS has none for it yet) renders the source order. A slot is bare only
115
+ when every page drawing the view places that bind. A dynamic route's view (`blog/[id].astro` →
116
+ `BlogPostView`) is wrapped the same way with `template`. Write it by hand in this shape when the
117
+ codemod refuses the view ([componentize.md](componentize.md) §5).
118
+ - The list is the published snapshot's, or the draft's when the Visual Editor frames a
119
+ server-rendered page (`prerender = false`). `blocks={…}` gives it yourself.
120
+
121
+ Check: build, then view source. `<!--bcms-sections:start page="home"-->` precedes the sections,
122
+ and each placed section's root carries `data-bcms-block` and `data-bcms-style`.
123
+
124
+ ## Bindings
125
+
126
+ A section root your own code renders spreads `sectionRootAttrs(block)` from `@bettercms-ai/astro`
127
+ (`data-bcms-block`, `data-bcms-style` and the block's style), so the editor can move it and offer
128
+ its spacing handles ([components.md](components.md) §5). It adds `data-bcms-hide` when `style.hideOn` is set: put `RESPONSIVE_CSS` (exported here) in your global CSS.
129
+
130
+ `<BcmsBlocks>` does not render a block outside its `window`, read against the `now` prop (default:
131
+ render time). Pass `showScheduled` on a draft preview to draw it, marked `data-bcms-window`
132
+ ([publishing.md](publishing.md) §6).
133
+
134
+ `bind` and `bindProps` from `@bettercms-ai/astro/bindings` produce the same attributes as the Next
135
+ helpers. Use them inside component instances so addresses resolve to the instance
136
+ ([bindings.md](bindings.md) §3).
137
+
138
+ ## Traps
139
+
140
+ | Symptom | Cause | Rule |
141
+ |---|---|---|
142
+ | Resized images 404 on a non-production site | `mediaUrl` still the production default | Set `PUBLIC_BCMS_MEDIA_URL` to that rung's API origin |
143
+ | Resized images still on the CDN after moving media | `mediaUrl` not changed | Set it to `mediaBaseUrl` from `get_project` |
144
+ | Component instances empty | `components` prop missing | Pass definitions to `BcmsBlocks` |
145
+ | A code section vanished after a build | Its slot is bare and the page's block list does not place its bind | Name it `code:<bind>`, or place the bind on the page |
146
+ | Build fails on `bettercms:config` | A page imports `BcmsSearch` or the virtual module on a build where `bettercms()` is not registered | Register it unconditionally. `BcmsSections`, `BcmsBlocks`, `BcmsImage` and `BcmsForm` need no integration |
147
+ | Draft link 500 | `BCMS_DRAFT_SECRET` unset | Set it on the server env, redeploy |
148
+ | `ReferenceError: X is not defined` from a `[slug].astro` route | `getStaticPaths()` reads a `const` declared in the frontmatter; Astro runs it in its own scope, before the page, seeing only imports | Declare the client or reader call inside `getStaticPaths`, or import it from a module |