@typeroll/mcp-server 0.38.1 → 0.41.1

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.
@@ -43,6 +43,37 @@ list_partials # check if header/footer already have content
43
43
  list_block_types # the per-site block palette — NEVER assume, always list
44
44
  ```
45
45
 
46
+ **Do not choose a content mode or file a platform gap before these calls
47
+ return.** For every required visual/behavioral element, map it to an existing
48
+ block or composition first. If the summary suggests a match, use
49
+ `read_block_type` to inspect the exact schema. Only call something “missing”
50
+ after checking capabilities, the complete palette, and custom block types.
51
+
52
+ Common requirements that are easy to misclassify:
53
+
54
+ | Requirement | Existing Typeroll primitive |
55
+ |---|---|
56
+ | Full-bleed hero flush below the header | `core/section` + `core/hero`; block-mode sections already own the full width and have no page-shell padding |
57
+ | Responsive icon/card grid | `core/grid` + `core/icon_box`, or `core/feature_grid`; set responsive fields with `set_block_responsive` |
58
+ | Custom cards backed by a collection | `core/repeater` / `core/collection_list` with a site-authored `item_compatible` block type as `item_block` |
59
+ | Grouped collection listing | `core/repeater` with `group_by`; array-valued fields place an item in every matching group |
60
+ | Breadcrumbs in a page template | `template/page_breadcrumbs` (verify that the relevant route supplies a breadcrumb trail) |
61
+ | Generated heading index | `core/table_of_contents`; choose `h2`, `h2-h3`, or `h2-h4` |
62
+ | Previous/next collection item links | `template/item_navigation` in the collection's block template; ordering follows `sort_field` / `sort_dir` |
63
+ | Download CTA that disappears without a file | `template/show_if` around a context-bound `core/button`; a dedicated download block is only editor convenience |
64
+ | Sticky/custom header and multi-column footer | Block-mode header/footer partials plus layout blocks, or one reusable custom block type |
65
+ | Cookie notice | `settings.cookie_consent`, not a page block |
66
+ | Consent copy owned by an installed Extension | `list_extension_installations` → `read_extension_installation` → `update_extension_installation_config`, using exact manifest schema keys |
67
+ | One-off HTML + JavaScript embed | `core/embed`; reusable widgets use a custom block type with `script` |
68
+ | CTA/button variants | `core/cta` and `core/button`, styled from site tokens or a narrowly scoped class |
69
+ | Two-column image/text | `core/media_card`, `core/feature_row`, or `core/columns` |
70
+ | Figures, captions and tables | `core/prose` / richtext; the sanitizer preserves these semantic tags |
71
+ | Full-width block page without a content shell | Native block mode; top-level `core/section` is unconstrained |
72
+ | Brand colors and typography | Site `colors`/`fonts` tokens consumed by core blocks |
73
+
74
+ Real gaps should say what was checked and why the nearest primitive is not
75
+ enough. “I did not see a dedicated block name” is not evidence by itself.
76
+
46
77
  ### 2. Brand + settings
47
78
 
48
79
  One `update_site_settings` call with every field you know:
@@ -52,6 +83,7 @@ One `update_site_settings` call with every field you know:
52
83
  "site_name": "Acme Studio",
53
84
  "tagline": "Short, punchy tagline",
54
85
  "language": "sv",
86
+ "trailing_slash": "always",
55
87
  "colors": {
56
88
  "primary": "#1a1a2e",
57
89
  "secondary": "#16213e",
@@ -70,11 +102,16 @@ One `update_site_settings` call with every field you know:
70
102
  Read it back with `read_site_settings`. Google Fonts names are
71
103
  case-sensitive display names ("Plus Jakarta Sans", not "plus jakarta").
72
104
 
73
- **Site icons are part of brand setup** — upload favicon (32–64px) and a
74
- 180×180 apple touch icon, set `favicon` + `apple_touch_icon`. No icon
75
- assets? Derive a proposal (see `tr-brand`). Also set `settings.logo` to
76
- the uploaded brand mark — it feeds OG/schema even if the header uses a
77
- different lockup.
105
+ **Site icons are part of brand setup** — upload favicon (32–64px), a
106
+ 180×180 apple touch icon, and a 192×192 app icon; set `favicon`,
107
+ `apple_touch_icon`, and `icon_192`. No icon assets? Derive a proposal (see
108
+ `tr-brand`). Also set `settings.logo` to the uploaded brand mark — it feeds
109
+ OG/schema even if the header uses a different lockup.
110
+
111
+ Set `iframe_allowed_hosts` when customer content embeds a provider outside
112
+ the built-in YouTube/Vimeo/Google Maps/Calendly set. Values are exact domain
113
+ hostnames, never URLs or wildcards. Read the setting back before deciding that
114
+ an iframe cannot be represented.
78
115
 
79
116
  ### 3. Header + footer partials
80
117
 
@@ -85,9 +122,10 @@ traps: clipped logos (no `overflow:hidden` near the logo), distorted logos
85
122
  (`height` + `width:auto`), and broken mobile menus. Fill the placeholders and
86
123
  restyle to the palette.
87
124
 
88
- Partials are usually simplest in HTML mode (one nav, a few links no
89
- per-field editing needed). Keep them lean; literal site name (no template
90
- engine in partials):
125
+ Partials can use either mode. Use HTML for a compact hand-authored nav, or
126
+ block mode when editors need per-field control or an installed Extension must
127
+ be placed there. Partials receive the same `{{site.*}}` render context as page
128
+ blocks, so literal brand data is optional rather than required:
91
129
 
92
130
  ```html
93
131
  <header class="site-header">
@@ -181,10 +219,15 @@ truth):
181
219
  `radius` field for rounded corners.
182
220
  - **Repeaters/listings:** `core/collection_list`, `gallery`,
183
221
  `feature_grid` etc. — alias blocks over `core/repeater`. Use these for
184
- collection-driven content instead of hand-writing listing markup.
185
- - **Forms:** `create_form`, then a `core/html` block carrying the plain
186
- `<form method="POST" action={submit_url}>` embed with the hidden
187
- `_token` see `tr-forms`.
222
+ collection-driven content instead of hand-writing listing markup. The base
223
+ repeater also supports `group_by`, group ordering/headings, multi-valued
224
+ membership, filters, custom `item_block`, and `item_overrides`.
225
+ - **Long-form navigation:** `core/table_of_contents` builds an anchor list
226
+ from page headings. Collection block templates use
227
+ `template/item_navigation` for deterministic previous/next links.
228
+ - **Forms:** `create_form`, then place `core/form` with its `form_id`.
229
+ HTML-mode pages use `<x-form id="…" />`; both paths render the same signed
230
+ shell and runtime. See `tr-forms`.
188
231
  - **`core/html`** is the escape hatch for the genuinely unique thing —
189
232
  not a default. If you reach for it more than once or twice per page,
190
233
  note why (that's block-library feedback).
@@ -211,6 +254,23 @@ text) renders as text, so emoji stand-ins keep working. Icons inherit
211
254
  size from font-size and color from `currentColor`/the block's color
212
255
  field. On older sites icons don't render — use emoji or CSS markers.
213
256
 
257
+ Editor schemas (template_capabilities_version ≥ 0.39.0): labelled enum
258
+ options, newline-edited string lists, nested object/repeating-array fields,
259
+ and internal-page pickers for URL fields are first-class. Do not flatten an
260
+ Extension's `props_schema` merely to make it editable.
261
+
262
+ For an Extension placed in an HTML header or footer, require
263
+ `supports_extension_html_partial_directive: true`. The broader
264
+ `supports_extension_html_directive` flag covers HTML page bodies and is not
265
+ proof that an older static build expands partial directives.
266
+
267
+ For a cross-page Extension flow, require both
268
+ `supports_extension_site_navigation` and `supports_extension_storage`. Use
269
+ `context.site.navigate("/path/")` and installation-scoped
270
+ `context.storage.session` rather than direct root-path navigation, Web Storage,
271
+ or personal data in query parameters. This keeps navigation inside the current
272
+ preview and preserves state without exposing it through URLs or referrers.
273
+
214
274
  Known limitations (honest list — don't fight them):
215
275
 
216
276
  - **`core/tabs` label icons don't render** (the tab strip is built
@@ -291,5 +351,5 @@ For migrated legacy pages or a hand-crafted one-off, `content_mode:
291
351
  labels (`affärsutveckling`, not the ASCII-folded slug), keep titles
292
352
  verbatim; slugs are derived for URLs only.
293
353
  - **Minimal JS.** Inline `<script>` in page content is stripped by the
294
- sanitizer. Interactivity ships via block-type `script` (requires the
295
- site's AI-scripts opt-in) or the human-managed `scripts_body_end`.
354
+ sanitizer. One-off interactivity uses `core/embed`; reusable interactivity
355
+ uses a block-type `script`; site-wide code belongs in `scripts_body_end`.
package/skills/tr-seo.md CHANGED
@@ -68,6 +68,12 @@ something different.
68
68
  ```
69
69
  update_site_settings {"default_seo_suffix": " — Acme Studio"}
70
70
 
71
+ # Set the canonical URL style once per site. Existing sites default to `always`.
72
+ update_site_settings {"trailing_slash": "always"}
73
+
74
+ # A page that must keep its exact campaign/title text can opt out.
75
+ update_page {"page_id": "campaign", "patch": {"append_seo_suffix": false}, "save": true}
76
+
71
77
  update_page page_id="home" patch={
72
78
  "seo_title": "Acme Studio — Inredningsdesign i Stockholm"
73
79
  }