@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 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. 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.";
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-`/`footer-` keys, anything promoted into 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.",
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? -> place the project's provisioned components
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 \u2014 variant, size and fullWidth are that block's own props and
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. Start from the
5973
- builtin blueprints \`list_components\` returns (\`builtin:*\`) instead of hand-writing block JSON.
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