@bettercms-ai/mcp 0.63.1 → 0.63.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/dist/index.js +17 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ import { AsyncLocalStorage } from "async_hooks";
|
|
|
15
15
|
import { z } from "zod";
|
|
16
16
|
|
|
17
17
|
// ../types/src/component.ts
|
|
18
|
-
var SECTION_DOCTRINE = "STRUCTURE (separate from schema): a page is composed of SECTIONS. NEVER build a page out of loose top-level heading/text/image/button/spacer blocks \u2014 they cannot be moved, duplicated or swapped as a unit, the visual editor cannot outline or name them, and every one of them becomes its own section in the editor. A hero of a headline, a lede and two CTAs is ONE section, not four. TWO SHAPES, and the choice is about REUSE. (1) A band that appears on more than one page, or that needs layout variants, is a COMPONENT with a `sectionType` \u2014 see create_component. Components sharing a `sectionType` are that section's VARIANTS (one Hero: 'Centered' for the home page and 'Two-column' for about, same prop keys so a swap keeps the content). This is also the only shape the editor's 'Add a section' picker can insert, and the only one that gets a family name and a variant switcher. (2) A genuinely one-off band on a single page is a `section` BLOCK whose `props.children` hold its blocks. THE TRADEOFF, stated in the present tense because it is real today: inside a component, ONLY the leaves a declared prop TARGETS are click-to-edit on the canvas \u2014 each declared prop's `target` is re-keyed to that PLACEMENT's own override address, so editing it changes this page and not the shared definition. A prop with no `target` still SHOWS as a dock control, but its override reaches no rendered slot, so editing it changes nothing on the page. Copy that no prop points at is worse still: no binding and no control, unreachable from click-to-edit AND from the dock, changeable only by editing the component definition, which rewrites every page that places it. A `section` block's children stay click-to-edit unconditionally. So when you choose a component, DECLARE A PROP \u2014 WITH A `target` \u2014 for every string, link and image a marketer will ever touch; a component with un-propped editable copy is the defect, not the component. In the dock an unset prop shows EMPTY and inherits the definition's default, so set props explicitly when you want the current copy visible there.
|
|
18
|
+
var SECTION_DOCTRINE = "STRUCTURE (separate from schema): a page is composed of SECTIONS. NEVER build a page out of loose top-level heading/text/image/button/spacer blocks \u2014 they cannot be moved, duplicated or swapped as a unit, the visual editor cannot outline or name them, and every one of them becomes its own section in the editor. A hero of a headline, a lede and two CTAs is ONE section, not four. TWO SHAPES, and the choice is about REUSE. (1) A band that appears on more than one page, or that needs layout variants, is a COMPONENT with a `sectionType` \u2014 see create_component. Components sharing a `sectionType` are that section's VARIANTS (one Hero: 'Centered' for the home page and 'Two-column' for about, same prop keys so a swap keeps the content). This is also the only shape the editor's 'Add a section' picker can insert, and the only one that gets a family name and a variant switcher. (2) A genuinely one-off band on a single page is a `section` BLOCK whose `props.children` hold its blocks. THE TRADEOFF, stated in the present tense because it is real today: inside a component, ONLY the leaves a declared prop TARGETS are click-to-edit on the canvas \u2014 each declared prop's `target` is re-keyed to that PLACEMENT's own override address, so editing it changes this page and not the shared definition. A prop with no `target` still SHOWS as a dock control, but its override reaches no rendered slot, so editing it changes nothing on the page. Copy that no prop points at is worse still: no binding and no control, unreachable from click-to-edit AND from the dock, changeable only by editing the component definition, which rewrites every page that places it. A `section` block's children stay click-to-edit unconditionally. So when you choose a component, DECLARE A PROP \u2014 WITH A `target` \u2014 for every string, link and image a marketer will ever touch; a component with un-propped editable copy is the defect, not the component. In the dock an unset prop shows EMPTY and inherits the definition's default, so set props explicitly when you want the current copy visible there. An IMPORTED site's components are its own (read the repo); its nav, footer and modals are the Layout. On a blank site, do not hand-write a band's JSON: start from a built-in section blueprint (list_components returns locked `builtin:*` blueprints with no projectId \u2014 hero-centered, hero-split, feature-grid-three, cta-banner and nine more), each already rooted in a `section` block with its editable leaves declared as props. INLINE its blockJson as a `section` block for a one-off band; for a recurring band, materialize the blueprint with create_component so it becomes project-scoped before implementation validation, Output or publication. Direct `builtin:*` component references exist only for legacy delivery compatibility. Two consecutive call-to-action buttons are two sibling `button` blocks inside the same section \u2014 never a `columns` block, which is a `repeat(N,1fr)` grid and would stretch each CTA to half the container. Buttons are inline-level and flow side by side on their own.";
|
|
19
19
|
var COMPONENT_PROP_TYPES = [
|
|
20
20
|
"text",
|
|
21
21
|
"richtext",
|
|
@@ -4201,7 +4201,7 @@ ${res.warnings.join("\n")}` : summary, res.data);
|
|
|
4201
4201
|
def(
|
|
4202
4202
|
"get_componentize_plan",
|
|
4203
4203
|
"Get the plan for turning this site's sections into components",
|
|
4204
|
-
"What this site's SECTIONS would become as components \u2014 a proposal that creates nothing and is computed live. For a site whose pages were DERIVED at import, each top-level field GROUP is one section: `hero-*` and `faq-*` keys, and the repeaters the import folded (`group-*`). Per page: each section's `groupKey`, `sectionType` family, leaf `fields` with their CMS values, `shapeHash`, and either the component already rendering it (`reuse.componentId`) or the proposed one (`reuse.proposedSlug`). Under `components`, a NEW one carries the exact `props` and `blockJson` create_component would take; an EXISTING one only `componentId`, `slug` and `name` (nothing is written for it). Every page gets its OWN components; a locale copy (`/fr`) reuses its default-locale page's. A COLLECTION TEMPLATE (dynamic page, `pattern: \"{slug}\"`) is planned ONCE, every prop reading the rendered entry: only its prose body and object-row lists are bands; frontmatter (author, images, tags, dates) stays entry fields. `pending` says why a group is not offered: `NO_GROUP_ROOT` (keys are still derive-lane names like `h1-welcome` \u2014 rename them into families first), `NOT_A_SECTION` (a lone scalar or the page's own metadata; `detail: ENTRY_METADATA` = collection-template frontmatter, `detail: DECLINED` = declined with componentize_sections `decline`), `IMAGE_AS_TEXT` (a text field holding an image path \u2014 make it an image field), `ALREADY_COMPONENTIZED`, `EMPTY_GROUP`, `NESTED_REPEATER` (three deep; two levels become a nested `table` sub-field), `PAGE_NOT_EMPTY` (blocks this lane does not own and will not overwrite). Chrome (`nav
|
|
4204
|
+
"What this site's SECTIONS would become as components \u2014 a proposal that creates nothing and is computed live. For a site whose pages were DERIVED at import, each top-level field GROUP is one section: `hero-*` and `faq-*` keys, and the repeaters the import folded (`group-*`). Per page: each section's `groupKey`, `sectionType` family, leaf `fields` with their CMS values, `shapeHash`, and either the component already rendering it (`reuse.componentId`) or the proposed one (`reuse.proposedSlug`). Under `components`, a NEW one carries the exact `props` and `blockJson` create_component would take; an EXISTING one only `componentId`, `slug` and `name` (nothing is written for it). Every page gets its OWN components; a locale copy (`/fr`) reuses its default-locale page's. A COLLECTION TEMPLATE (dynamic page, `pattern: \"{slug}\"`) is planned ONCE, every prop reading the rendered entry: only its prose body and object-row lists are bands; frontmatter (author, images, tags, dates) stays entry fields. `pending` says why a group is not offered: `NO_GROUP_ROOT` (keys are still derive-lane names like `h1-welcome` \u2014 rename them into families first), `NOT_A_SECTION` (a lone scalar or the page's own metadata; `detail: ENTRY_METADATA` = collection-template frontmatter, `detail: DECLINED` = declined with componentize_sections `decline`), `IMAGE_AS_TEXT` (a text field holding an image path \u2014 make it an image field), `ALREADY_COMPONENTIZED`, `EMPTY_GROUP`, `NESTED_REPEATER` (three deep; two levels become a nested `table` sub-field), `PAGE_NOT_EMPTY` (blocks this lane does not own and will not overwrite). Chrome (`nav`/`footer`/`modal`: LAYOUT_CHROME, or in the Layout) is NEVER a section: edit it through the Layout. READ `summary: true` FIRST \u2014 the full plan runs to hundreds of KB; `paged` pages it (409 PLAN_CHANGED = start again); the unpaged full read is what `--plan plan.json` takes. Keep the `digest` \u2014 componentize_sections refuses any other.",
|
|
4205
4205
|
z.object({
|
|
4206
4206
|
summary: z.boolean().optional().describe("true = no values: each section's groupKey, family, pending and component slug. Read this first."),
|
|
4207
4207
|
paged: z.boolean().optional().describe("true = 10 pages at a time; the response carries `page`, `pageCount` and a `cursor` for the next."),
|
|
@@ -5547,7 +5547,8 @@ DERIVED at import, where the componentize lane in \xA710 reuses every field.
|
|
|
5547
5547
|
A fixed cluster of fields? -> group (never a 1-item repeater)
|
|
5548
5548
|
A repeating cluster? -> repeater
|
|
5549
5549
|
A list of plain strings? -> array (never a repeater of one text)
|
|
5550
|
-
Site-wide nav/footer?
|
|
5550
|
+
Site-wide nav/footer/modal? -> the LAYOUT (get_layout/update_layout), never a
|
|
5551
|
+
page section and never one component per page
|
|
5551
5552
|
|
|
5552
5553
|
## 3. Anatomy of a real section component
|
|
5553
5554
|
|
|
@@ -5953,7 +5954,8 @@ below is one heading of that ask.
|
|
|
5953
5954
|
**1. Global elements.** Navbar, mobile nav, header and footer are the LAYOUT, not page content:
|
|
5954
5955
|
\`get_layout\` then \`update_layout\`, and a chrome COMPONENT is placed into a Layout section with
|
|
5955
5956
|
the \`add-component\` command. CTA buttons are \`button\` BLOCKS inside the section that uses them,
|
|
5956
|
-
exposed as \`text\` + \`url\` props
|
|
5957
|
+
exposed as \`text\` + \`url\` props that target that ONE block \u2014 never the words as a separate text
|
|
5958
|
+
block beside it, or the Button panel edits nothing \u2014 variant, size and fullWidth are that block's own props and
|
|
5957
5959
|
\`style\`, never a standalone Button component. Rich text is a \`richtext\` prop over a
|
|
5958
5960
|
\`richtext\`/\`text\` block. Forms are \`create_form\` plus a \`form\` block, and form FIELDS are the
|
|
5959
5961
|
one place the platform models \`required\`, \`placeholder\`, \`helpText\` and real \`validation\`
|
|
@@ -5969,8 +5971,11 @@ site's code and say so in your final summary.
|
|
|
5969
5971
|
Pricing, FAQ, Contact, Newsletter, CTA, Stats, Logo cloud, Content\u2026) and components sharing one
|
|
5970
5972
|
are its VARIANTS \u2014 give a family the same prop KEYS or a swap drops content. A one-off band
|
|
5971
5973
|
still gets its own component: its own family, plus \`allowedOn: ["slug:<page>"]\`. A component
|
|
5972
|
-
with NO \`sectionType\` never appears in the editor's "Add a section" picker.
|
|
5973
|
-
builtin blueprints \`list_components\` returns (\`builtin:*\`) instead of hand-writing block
|
|
5974
|
+
with NO \`sectionType\` never appears in the editor's "Add a section" picker. On a BLANK site, start
|
|
5975
|
+
from the builtin blueprints \`list_components\` returns (\`builtin:*\`) instead of hand-writing block
|
|
5976
|
+
JSON. On an IMPORTED site, never materialize a builtin: read the repo's own components first
|
|
5977
|
+
(\`src/components\`, its sections folder) and make ONE CMS component per source component, named
|
|
5978
|
+
as the source names it \u2014 the site's Pricing section is "Pricing", not "Section 2" or "Simple".
|
|
5974
5979
|
On a DERIVED site run \`get_componentize_plan\` \u2192 \`componentize_sections\` FIRST \u2014 it does most
|
|
5975
5980
|
of this in one call, and once \`components\` is recorded each release of a site derived at IMPORT
|
|
5976
5981
|
runs it in bind mode and publishes the components, so expect ALREADY_COMPONENTIZED \u2014 the placements it wrote are
|
|
@@ -5984,6 +5989,12 @@ Navigation, Actions, Content, Forms, Media, Sections, Page-specific. \`category\
|
|
|
5984
5989
|
axis: it is the picker TAB (hero / content / social-proof / conversion for sections; navbar /
|
|
5985
5990
|
footer for chrome; form; custom for page-specific).
|
|
5986
5991
|
|
|
5992
|
+
**3b. Group the fields the way the source groups them.** A price, a stat's figure and a badge are
|
|
5993
|
+
props of their own ("Price", "Stat value"), never folded into a sentence. Give every component of
|
|
5994
|
+
more than ~8 props \`ui.group\`s that mirror its markup \u2014 Content, Call to action, Media \u2014 and
|
|
5995
|
+
\`ui.collapsed\` on the secondary ones (\xA714). A flat list of 20 props named by their copy is the
|
|
5996
|
+
form editors cannot read.
|
|
5997
|
+
|
|
5987
5998
|
**4. Editor fields are \`props\`.** Types: \`text richtext image url boolean number select group
|
|
5988
5999
|
table slot form\`. Always set \`defaultValue\`. \`form\` points at ONE Form document: target a
|
|
5989
6000
|
\`form\` block's \`props\` and set \`defaultValue\` to \`{formId}\`. NEVER re-declare a form's fields
|