@se-studio/skills 1.5.4 → 1.5.6

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @se-studio/skills
2
2
 
3
+ ## 1.5.6
4
+
5
+ ### Patch Changes
6
+
7
+ - Media wrapper entries now default their `name` (Contentful list label) to the linked asset's title when created via `create media` or `visualAssetFilename` shorthands. Document the convention in editor playbooks and skills; avoid migration-style `Wrapper for {assetId}` labels.
8
+
9
+ ## 1.5.5
10
+
11
+ ### Patch Changes
12
+
13
+ - d1a119c: Add `contentful-cms-create-editor-playbooks` skill and reference docs for customer editor playbook rollouts (Pedestal, OM1, PointMe, SE website).
14
+
3
15
  ## 1.5.4
4
16
 
5
17
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@se-studio/skills",
3
- "version": "1.5.4",
3
+ "version": "1.5.6",
4
4
  "description": "SE Studio agent skills for marketing site development with Contentful CMS",
5
5
  "repository": {
6
6
  "type": "git",
@@ -0,0 +1,160 @@
1
+ # Editor playbook patterns (Brightline reference)
2
+
3
+ Patterns from the Brightline + BrightLife Kids rollout (`brightline-sites` `docs/cms-editor/`). Use as templates when authoring playbooks for other customers.
4
+
5
+ ## Two-file pattern
6
+
7
+ Every **specialized page category** gets two files:
8
+
9
+ | File | Role |
10
+ |------|------|
11
+ | `docs/cms-editor/<projectKey>/<topic>.md` | Full playbook — URL patterns, content stack, reference pages, component mapping |
12
+ | `docs/cms-editor/<projectKey>/tasks/<topic>.md` | Short **capability task** — intent phrases + step checklist for `tasks-index` |
13
+
14
+ Example (Brightline condition pages):
15
+
16
+ - `brightline/condition-program-pages.md` → `cms-edit://customer/condition-program-pages`
17
+ - `brightline/tasks/condition-program-pages.md` → `cms-edit://customer/task-condition-program-pages`
18
+
19
+ Task stubs are **not** copies of the full playbook — they route agents to read the full resource first.
20
+
21
+ ## Task stub format
22
+
23
+ ```markdown
24
+ # Capability: Condition & therapy program pages
25
+
26
+ ## Intent phrases
27
+
28
+ - edit a condition page
29
+ - new therapy program page
30
+
31
+ ## Requires capabilities
32
+
33
+ `pages`
34
+
35
+ ## Prerequisites
36
+
37
+ - Read `cms-edit://customer/condition-program-pages` (full playbook)
38
+ - Read `cms-edit://customer/pages` for general page rules
39
+ - `cms_edit ["index", "sync"]` when cloning from templates
40
+
41
+ ## Steps
42
+
43
+ 1. Identify URL under `/what-we-treat/` or `/care/therapy-programs/`
44
+ 2. Clone reference page (`task-clone-page`)
45
+ 3. Update Hero, FAQ collection, CTAs
46
+ 4. `preview urls` on staging
47
+ 5. `diff` → `save` → `task-publish-handoff`
48
+ ```
49
+
50
+ **Parser rules** (`packages/contentful-cms/src/editor-pack/capabilities.ts`):
51
+
52
+ - Title from `# Capability: <text>`
53
+ - Intent phrases from bullet list under `## Intent phrases`
54
+ - Resource name = `task-` + filename slug (without `.md`)
55
+
56
+ ## `pages.md` hub pattern
57
+
58
+ General `pages.md` is the **router** — not a duplicate of every specialized playbook.
59
+
60
+ Include:
61
+
62
+ 1. **Table** linking page types → `cms-edit://customer/<topic>` resources
63
+ 2. **When to use** — path prefixes, clone vs net-new
64
+ 3. **Templates** — `cms-edit list --type template` table
65
+ 4. **Reference pages** — 4–8 canonical clone sources with notes
66
+ 5. **Doc section → component mapping** — brief headings to registered types
67
+ 6. **Creating pages** — `task-create-page`, `task-create-from-document`, dry-run
68
+ 7. **Preview / publish handoff**
69
+
70
+ Brightline excerpt:
71
+
72
+ ```markdown
73
+ | Page type | Playbook |
74
+ |-----------|----------|
75
+ | Condition or therapy program | `cms-edit://customer/condition-program-pages` |
76
+ | Insurance / pricing / cost | `cms-edit://customer/insurance-pricing-pages` |
77
+ | Blog article | `cms-edit://customer/articles` |
78
+ ```
79
+
80
+ ## Specialized playbook sections
81
+
82
+ | Section | Purpose |
83
+ |---------|---------|
84
+ | URL patterns | Prefix table with 2+ real examples |
85
+ | Typical content stack | Ordered component/collection list |
86
+ | Reference pages | "Clone when" column |
87
+ | Hero / template guidance | Site-specific design rules |
88
+ | FAQ / SEO / schema notes | When clinically or legally sensitive |
89
+ | Workflow | Numbered steps |
90
+ | Out of scope | Prevents wrong template or duplicate blocks |
91
+
92
+ Fetch live markdown when `website.markdownAccess` is enabled: `https://<prod><path>.md`
93
+
94
+ ## Tier system (Brightline)
95
+
96
+ ### P0 — ship first
97
+
98
+ | Brightline | BLK |
99
+ |------------|-----|
100
+ | `pages.md` | `pages.md` |
101
+ | `ARTICLES.md` | `articles.md` |
102
+ | `condition-program-pages` | `parent-coaching-topic-pages` |
103
+ | `insurance-pricing-pages` | — |
104
+ | `landing-pages-paid-media` | — |
105
+
106
+ ### P1
107
+
108
+ | Brightline | BLK |
109
+ |------------|-----|
110
+ | `provider-pages` | `bilingual-locale-pages` |
111
+ | `location-pages` | `resources-hub-pages` |
112
+ | `partner-pages` | — |
113
+
114
+ ### P2
115
+
116
+ | Brightline | BLK |
117
+ |------------|-----|
118
+ | `legal-policy-pages` | `legal-policy-pages` |
119
+ | `learning-hub-hub-pages` | — |
120
+
121
+ ### Skipped (both sites)
122
+
123
+ - `people.md` — `enablePerson=false`; clinicians covered by `provider-pages.md` on Brightline
124
+
125
+ ## Other playbook types
126
+
127
+ | File | When |
128
+ |------|------|
129
+ | `articles.md` / `ARTICLES.md` | Article types, tag rules, featuredImage vs visuals |
130
+ | `people.md` | `enablePerson=true` — team profiles, author import |
131
+ | `blog-tag-matrix.md` | Complex tag governance (Brightline) |
132
+ | `site-facts.json` | Canonical support email, phone — becomes `site-facts` resource |
133
+ | `tasks/*.md` only | Overrides for core tasks (e.g. `import-blog-tag-matrix`) |
134
+
135
+ ## Generator behaviour
136
+
137
+ From `packages/contentful-cms/src/editor-pack/generate.ts`:
138
+
139
+ - `articles.md` and `ARTICLES.md` → `articles` resource (not duplicated as separate basename)
140
+ - `pages.md` → sets `hasPagesPlaybook` in capabilities
141
+ - Other `*.md` in project root → resource name = kebab-case basename
142
+ - `tasks/*.md` → `task-<slug>` merged into `tasks-index.md`
143
+
144
+ ## Naming conventions
145
+
146
+ - **Filenames:** kebab-case, match URL family (`legal-policy-pages`, `resources-hub-pages`)
147
+ - **Resource URIs:** `cms-edit://customer/<basename>` — no `.md` suffix
148
+ - **projectKey:** must match `project.json` `projectKey` exactly (`brightline`, not `brightline-website`)
149
+
150
+ ## Commit message pattern
151
+
152
+ ```
153
+ docs(cms-editor): add Brightline P0 editor playbooks
154
+
155
+ - pages.md hub + condition/insurance/landing playbooks
156
+ - task stubs for tasks-index
157
+ - regenerate editor-pack
158
+ ```
159
+
160
+ Split P1/P2 into separate commits for easier review.
@@ -0,0 +1,225 @@
1
+ # Editor playbook rollout — project queue
2
+
3
+ Suggested order after Brightline + BLK completion. Each project: audit → P0 → regen → doctor → push `develop` → P1 → P2.
4
+
5
+ Skill: **`contentful-cms-create-editor-playbooks`**
6
+
7
+ ## Rollout order
8
+
9
+ | # | Project | Repo path | Branch | Hosted MCP |
10
+ |---|---------|-----------|--------|------------|
11
+ | 1 | Pedestal Health | `~/source/customers/pedestal/pedestal-sites` | `develop` | `pedestal.content.se.studio` (verify in repo) |
12
+ | 1b | Headwater Science | same monorepo | `develop` | separate space — second pass |
13
+ | 2 | OM1 | `~/source/customers/om1/om1-website` | `develop` | `om1.content.se.studio` |
14
+ | 3 | PointMe | `~/source/customers/pointme/develop-marketing-site` | `develop` | `pointme.content.se.studio` |
15
+ | 4 | SE Studio | `~/source/se/se-website-2026` | `develop` | `se-website-2026.content.se.studio` |
16
+
17
+ ---
18
+
19
+ ## 1. Pedestal (`pedestal-sites`)
20
+
21
+ **Config:** `cms-edit/pedestal-health/project.json` → `projectKey: pedestal-health`, `appDir: apps/pedestal-website`
22
+
23
+ **Current state:** `docs/cms-editor/pedestal-health/ARTICLES.md` only — no `pages.md`, no specialized playbooks.
24
+
25
+ **Routing signals** (`apps/pedestal-website/src/lib/constants.ts`):
26
+
27
+ | Flag | Value |
28
+ |------|-------|
29
+ | `enablePerson` | `true` → need `people.md` |
30
+ | `ARTICLES_BASE` | `''` (root-relative article URLs) |
31
+ | `markdownArticleTypeSlugs` | `resources/publications`, `resources/news` |
32
+ | `enablePrimaryTagPartOfSlug` | `true` |
33
+ | Homepage | `index` (standard — omit `website.homepageSlug` in `project.json`) |
34
+
35
+ ### Suggested tiers
36
+
37
+ **P0**
38
+
39
+ | Playbook | Rationale |
40
+ |----------|-----------|
41
+ | `pages.md` | Doctor requires when pages enabled |
42
+ | `articles.md` | Rename/normalize from `ARTICLES.md` (either filename works; pick one) |
43
+ | `people.md` | Persons enabled + `/people/` routes |
44
+ | `publications-pages.md` | Core product — publications with poster/download rules |
45
+ | `news-pages.md` | Press/news article type patterns |
46
+
47
+ **P1**
48
+
49
+ | Playbook | Rationale |
50
+ |----------|-----------|
51
+ | `therapeutic-area-pages.md` | Disease/TA landing pages if distinct URL prefix |
52
+ | `solutions-pages.md` | Product/solution family pages |
53
+ | `resources-hub-pages.md` | `/resources/` index behaviour |
54
+
55
+ **P2**
56
+
57
+ | Playbook | Rationale |
58
+ |----------|-----------|
59
+ | `legal-policy-pages.md` | Privacy, terms, compliance |
60
+
61
+ **Headwater (`headwater-science`):** Repeat audit separately — same monorepo patterns but different content model and `projectKey`. Only `ARTICLES.md` exists today.
62
+
63
+ ---
64
+
65
+ ## 2. OM1 (`om1-website`)
66
+
67
+ **Config:** `cms-edit/project.json` → `projectKey: om1`, single-site layout
68
+
69
+ **Current state:** No `docs/cms-editor/` files — start from scratch.
70
+
71
+ **Routing signals:**
72
+
73
+ | Flag | Value |
74
+ |------|-------|
75
+ | `enablePerson` | `true` → `people.md` |
76
+ | `ARTICLES_BASE` | `/resources` |
77
+ | `PEOPLE_BASE` | `/team` |
78
+ | `enableArticleTypeIndex` | `true` |
79
+ | `enablePrimaryTagPartOfSlug` | `true` |
80
+ | `TOPICLESS_ARTICLE_TYPE_SLUGS` | `ebooks` — document in articles playbook |
81
+
82
+ ### Suggested tiers
83
+
84
+ **P0**
85
+
86
+ | Playbook | Rationale |
87
+ |----------|-----------|
88
+ | `pages.md` | General marketing pages |
89
+ | `articles.md` | Resources hub — blog, ebooks, publications |
90
+ | `people.md` | Team profiles at `/team/` |
91
+ | `resource-article-pages.md` | Standard `/resources/{type}/{topic}/{slug}/` articles |
92
+
93
+ **P1**
94
+
95
+ | Playbook | Rationale |
96
+ |----------|-----------|
97
+ | `ebook-pages.md` | Topicless URL shape for ebooks |
98
+ | `solutions-pages.md` | Product/solution pages if distinct prefix |
99
+ | `events-webinars-pages.md` | If event content type exists |
100
+
101
+ **P2**
102
+
103
+ | Playbook | Rationale |
104
+ |----------|-----------|
105
+ | `legal-policy-pages.md` | Compliance |
106
+
107
+ **Audit tip:** Inventory `/resources/` paths from sitemap; peek top-traffic solution and resource pages before writing component stacks.
108
+
109
+ ---
110
+
111
+ ## 3. PointMe (`develop-marketing-site`)
112
+
113
+ **Config:** `cms-edit/project.json` → `projectKey: pointme`
114
+
115
+ **Current state:** No `docs/cms-editor/` — start from scratch.
116
+
117
+ **Routing signals:**
118
+
119
+ | Flag | Value |
120
+ |------|-------|
121
+ | `enablePerson` | `true` |
122
+ | `ARTICLES_SLUG` | `insights` |
123
+ | `PEOPLE_BASE` | `/insights/author` (authors under insights, not `/people/`) |
124
+ | `enableArticleTypeIndex` | `true` |
125
+ | `enableTagsIndex` | `false` — tag pages under `/insights/{tag}/` |
126
+ | `enablePrimaryTagPartOfSlug` | `false` |
127
+
128
+ **Note:** Marketing site only — product app (`/home`, `/search`) is AWS; playbooks cover Vercel marketing routes only.
129
+
130
+ ### Suggested tiers
131
+
132
+ **P0**
133
+
134
+ | Playbook | Rationale |
135
+ |----------|-----------|
136
+ | `pages.md` | About, concierge, marketing LPs |
137
+ | `articles.md` | Insights blog — primary content type |
138
+ | `insights-author-pages.md` | Author profiles at `/insights/author/{slug}/` (not generic `people.md` — custom PEOPLE_BASE) |
139
+ | `insights-hub-pages.md` | `/insights/` index and tag landing pages |
140
+
141
+ **P1**
142
+
143
+ | Playbook | Rationale |
144
+ |----------|-----------|
145
+ | `concierge-pages.md` | If `/concierge/` is a distinct template family |
146
+ | `landing-pages-paid-media.md` | Campaign LPs if `indexed: false` pattern exists |
147
+
148
+ **P2**
149
+
150
+ | Playbook | Rationale |
151
+ |----------|-----------|
152
+ | `legal-policy-pages.md` | Privacy, terms |
153
+
154
+ **Audit tip:** Map CloudFront-routed marketing paths only; exclude AWS product URLs from page inventory.
155
+
156
+ ---
157
+
158
+ ## 4. SE Studio (`se-website-2026`) — hard mode
159
+
160
+ **Config:** `cms-edit/project.json` → `projectKey: se2026`
161
+
162
+ **Current state:** `docs/cms-editor/se2026/pages.md` and `articles.md` exist — **extend, don't replace blindly**.
163
+
164
+ **Why hard:** Site is **not designed for arbitrary custom marketing pages**. Page model is a small set of reference layouts (home, about, services, demo landing) using **General Page** template with `topContent` + `content`. New pages should **clone references**, not invent new component families.
165
+
166
+ **Routing signals:**
167
+
168
+ | Flag | Value |
169
+ |------|-------|
170
+ | `enablePerson` | `false` — **no `people.md`** |
171
+ | Team content | **Person** entries in **Team grid** collection |
172
+ | `enableTag` | `false` — simpler article model |
173
+ | `ARTICLES_BASE` | `''` — work/video/blog article types |
174
+ | `enableArticleTypeIndex` | `false` |
175
+
176
+ ### Suggested work (not traditional P0/P1/P2)
177
+
178
+ | Action | Rationale |
179
+ |--------|-----------|
180
+ | **Tighten** existing `pages.md` | Ensure reference table, component mapping, and out-of-scope are current |
181
+ | **Tighten** `articles.md` | Work / video / blog rules, case study picks in **Article browser** collections |
182
+ | **Avoid** many specialized page playbooks | No `/providers/`-style families |
183
+ | Optional `work-case-study-pages.md` | If editors frequently add case studies |
184
+ | Optional `demo-landing-pages.md` | Campaign clones from `/demo-landing` |
185
+ | **Do not** add `people.md` | Use articles + Team grid Person guidance inside `pages.md` |
186
+
187
+ ### SE website editor guardrails (put in `pages.md`)
188
+
189
+ - New marketing pages: clone `/about`, `/services`, or `/demo-landing` — not blank canvas
190
+ - Homepage slug `index` (URL `/`)
191
+ - Agent test pages: `indexed: false`
192
+ - Component gaps → **Generic** fallback + engineering flag
193
+ - Read `cms-edit://customer/brand` for voice
194
+
195
+ **Audit tip:** `cms-edit peek --page-slug /about` and `/services` — document exact collection nesting before any new playbook.
196
+
197
+ ---
198
+
199
+ ## Per-project audit checklist
200
+
201
+ Copy into working notes for each site:
202
+
203
+ ```
204
+ [ ] project.json validated
205
+ [ ] constants.ts flags recorded
206
+ [ ] sitemap categories table
207
+ [ ] templates listed (cms-edit list --type template)
208
+ [ ] 3+ reference pages peek'd
209
+ [ ] capabilities.json reviewed
210
+ [ ] P0 playbook list approved by user
211
+ [ ] pages.md hub links all specialized playbooks
212
+ [ ] task stub per specialized playbook
213
+ [ ] editor-pack regenerated
214
+ [ ] project doctor clean
215
+ [ ] pushed to develop
216
+ ```
217
+
218
+ ## Completed reference
219
+
220
+ **Brightline + BLK** (`brightline-sites`) — full P0–P2 shipped. Use as gold standard:
221
+
222
+ - `docs/cms-editor/brightline/` — 8 specialized + hub + articles + blog-tag-matrix
223
+ - `docs/cms-editor/brightlifekids/` — 6 specialized + hub + articles
224
+
225
+ See `PATTERNS.md` for tier tables.
@@ -8,6 +8,10 @@
8
8
  "major": 11,
9
9
  "engines": "11.x"
10
10
  },
11
+ "minimumReleaseAge": {
12
+ "minutes": 1440,
13
+ "exclude": ["@se-studio/*"]
14
+ },
11
15
  "projects": [
12
16
  {
13
17
  "key": "se-core-product",
@@ -30,6 +30,8 @@ Use this skill when you need to read or edit content in Contentful CMS using the
30
30
  All `save` operations create **draft** versions. A human must review and publish in Contentful.
31
31
 
32
32
  **Assets:** Upload **is** supported (`asset upload`). Default workflow: **search and reuse** existing assets first (`index sync` → `asset search`). When uploading:
33
+ - **Hosted MCP:** always `cms_edit_request_staged_upload` → curl → `asset upload --staged` (never `--base64`)
34
+ - **Local CLI:** `--base64` or `--url` when user approves local CLI
33
35
  - Use a **sensible fileName** and **descriptive title** (and alt text where the site uses it)
34
36
  - Avoid oversized images — width over **2000px** is usually wasteful for web (exact limits vary by project; check `asset audit` / media review guidance)
35
37
  - Prefer `--if-exists-by-filename` to avoid duplicates
@@ -120,7 +122,7 @@ cms-edit set @c0 anchor "hero-section"
120
122
  cms-edit set @c1:cmsLabel="Hero — School avoidance" @c2:cmsLabel="What is school avoidance?" @c3:cmsLabel="Signs of school avoidance"
121
123
  cms-edit set @c1:heading="Title A" @c2:heading="Title B"
122
124
  ```
123
- Each token is `@ref:fieldName=value`. All values are scalar (string, boolean, number). Flags like `--link`, `--links`, `--file` do not apply in multi mode.
125
+ Each token is `@ref:fieldName=value`. All values are scalar (string, boolean, number). Flags like `--link`, `--links`, `--json` do not apply in multi mode.
124
126
 
125
127
  **Entry link fields** (template, articleType, etc. — value is the linked entry ID):
126
128
  ```bash
@@ -158,7 +160,7 @@ For any content with multiple paragraphs or newlines, use `printf` piped to stdi
158
160
  printf '## Why it matters\n\nOur platform helps teams **move faster**.\n\n- Instant setup\n- No code required\n' | cms-edit rtf @c1 body --markdown -
159
161
 
160
162
  # Also correct — file input
161
- cms-edit rtf @c1 body --markdown --file path/to/file.md
163
+ cms-edit rtf @c1 body --markdown --content "# Heading\n\nBody."
162
164
  cms-edit rtf @c1 body --markdown - < path/to/file.md
163
165
  ```
164
166
 
@@ -170,7 +172,7 @@ cms-edit rtf @c1 body --markdown "Simple single-paragraph body text with **bold*
170
172
 
171
173
  **Surgical rich text replace** (compliance / quidget tokens — does not re-import the whole field):
172
174
 
173
- - Matching is **per Contentful text node** only. If the author split a phrase with bold (e.g. `**Annual fee: **$95`), the string `Annual fee: $95` will **not** match as one piece; use a shorter `--find` or full `rtf … --file`.
175
+ - Matching is **per Contentful text node** only. If the author split a phrase with bold (e.g. `**Annual fee: **$95`), the string `Annual fee: $95` will **not** match as one piece; use a shorter `--find` or full `rtf … --content`.
174
176
  - Quidget strings contain `*`, which Markdown would treat as italic — use **`--replace-plain`**, not `--replace`.
175
177
 
176
178
  ```bash
@@ -246,7 +248,7 @@ Same as Component plus:
246
248
  When adding body content and a CTA (e.g. PDF download) to an article:
247
249
 
248
250
  1. `cms-edit open --article-slug <slug>` (or `open --id <id>`)
249
- 2. Set body: `cms-edit rtf @<ref> body --markdown "..."` or `--markdown --file path/to.md`. If you need to add a body component first, use `add` then `rtf`.
251
+ 2. Set body: `cms-edit rtf @<ref> body --markdown "..."` or `--content` / `--base64`. If you need to add a body component first, use `add` then `rtf`.
250
252
  3. `cms-edit add CTA --target bottomContent`
251
253
  4. Set CTA links: use `--type external --label "Download PDF" --href <url>` for an external PDF URL, or `--type download --label "Download PDF" --asset-id <asset-id>` for a Contentful asset (get the ID from `cms-edit asset search "..."` or `asset info <id>`).
252
254
  5. `cms-edit save`
@@ -369,13 +371,23 @@ cms-edit asset search "hero background"
369
371
  cms-edit asset search --filename istockphoto-123.jpg
370
372
  cms-edit asset search --filename-match 'istockphoto-.*'
371
373
 
372
- # Upload from local file, URL, or base64
373
- cms-edit asset upload ./poster.jpg --title "Poster"
374
+ # Local CLI — URL or base64 (hosted MCP rejects --base64)
374
375
  cms-edit asset upload --url https://example.com/image.jpg --if-exists-by-filename
375
376
  cms-edit asset upload --base64 "$B64" --mime image/png --file-name poster.png
376
377
 
377
- # Upload and create a Media wrapper in one step
378
- cms-edit asset upload ./figure.png --with-media --media-name "Figure 1" --media-position Middle
378
+ # Hosted MCP — always staged upload for binary files
379
+ # cms_edit_request_staged_upload → curl uploadUrl → consumeArgs
380
+ # cms_edit ["asset", "upload", "--staged", "<uploadId>", "--mime", "image/png", "--file-name", "photo.png"]
381
+
382
+ # Upload and create a Media wrapper in one step (--media-name defaults to asset title)
383
+ cms-edit asset upload ./figure.png --with-media --media-position Middle
384
+
385
+ # Create a Media wrapper for an existing asset (name defaults to asset title)
386
+ cms-edit create media --asset-id <asset-id>
387
+
388
+ # Fix a badly labelled Media wrapper (migration "Wrapper for …" labels)
389
+ cms-edit batch set <media-entry-id>:name=<asset-title>
390
+ cms-edit batch save
379
391
 
380
392
  # Get asset details
381
393
  cms-edit asset info 5xKj2abcDef
@@ -430,10 +442,10 @@ cms-edit create tag --slug easl-congress-2026 --name "EASL Congress 2026" --tag-
430
442
  --description "Research presented at EASL Congress 2026." --featured-image <logoAssetId>
431
443
 
432
444
  # Full fields via JSON
433
- cms-edit create tag --json-file tag.json --tag-type presentation-type --if-not-exists
445
+ cms-edit create tag --json '{"slug":"presentation"}' --tag-type presentation-type --if-not-exists
434
446
 
435
447
  # Batch bootstrap
436
- cms-edit create taxonomy-from-json --file taxonomy.json --if-not-exists
448
+ cms-edit create taxonomy-from-json --json '{"tagTypes":[...]}' --if-not-exists
437
449
 
438
450
  # Idempotent single-entry creates
439
451
  cms-edit create tag-type --slug conference-venue --name "Conference Venue" --if-not-exists
@@ -664,9 +676,9 @@ cms-edit peek --id <entryId> # Look up by entry ID
664
676
  Run a sequence of operations from a JSON file or stdin.
665
677
 
666
678
  ```bash
667
- cms-edit batch run --file ops.json # Run batch ops from file
679
+ cms-edit batch run --json '[...]' # Run batch ops from inline JSON
668
680
  echo '[...]' | cms-edit batch run # Pipe from stdin
669
- cms-edit batch run --file ops.json --dry-run # Validate without saving
681
+ cms-edit batch run --json '[...]' --dry-run # Validate without saving
670
682
  ```
671
683
 
672
684
  Supported ops: `open`, `set`, `rtf`, `rtf-replace`, `save`, `add`, `links-add`.
@@ -700,8 +712,8 @@ Example `ops.json` — update an existing page with a new CTA that has two butto
700
712
  Create a complete page or article — including all components, fields, and CTA links — from a single declarative JSON file. This is the recommended approach for creating multiple pages or articles in bulk.
701
713
 
702
714
  ```bash
703
- cms-edit create from-json --file page.json # Create from file
704
- cms-edit create from-json --file page.json --dry-run # Preview without writing
715
+ cms-edit create from-json --json '{...}' # Create from inline JSON
716
+ cms-edit create from-json --json '{...}' --dry-run # Preview without writing
705
717
  cat page.json | cms-edit create from-json # Pipe from stdin
706
718
  ```
707
719
 
@@ -0,0 +1,266 @@
1
+ ---
2
+ name: contentful-cms-create-editor-playbooks
3
+ description: "Create and ship cms-editor playbooks for customer sites (audit page inventory, tier P0/P1/P2 playbooks, task stubs, regenerate editor-pack). Use for Pedestal, OM1, PointMe, SE website, or repeating the Brightline playbook rollout."
4
+ ---
5
+
6
+ # Create cms-editor playbooks
7
+
8
+ Use this skill when a customer site needs **hosted MCP editor playbooks** — the `docs/cms-editor/<projectKey>/` handbooks that become `cms-edit://customer/*` resources after editor-pack generation.
9
+
10
+ **Reference files** (read when drafting playbooks):
11
+
12
+ | File | Purpose |
13
+ |------|---------|
14
+ | `.agents/references/contentful-cms-editor-playbooks/PATTERNS.md` | Two-file pattern, sections, naming, Brightline examples |
15
+ | `.agents/references/contentful-cms-editor-playbooks/PROJECT-ROLLOUT.md` | Rollout queue (Pedestal → OM1 → PointMe → SE website) and per-site audit hints |
16
+
17
+ ## When to use
18
+
19
+ | Situation | Action |
20
+ |-----------|--------|
21
+ | New site with only `ARTICLES.md` or no playbooks | Full rollout (audit → P0 → regen → doctor) |
22
+ | Site has page categories editors ask about repeatedly | Add specialized playbook + task stub |
23
+ | After Brightline-style rollout on another customer | Follow this skill end-to-end |
24
+ | User says "playbooks for Pedestal / OM1 / PointMe / SE website" | Read `PROJECT-ROLLOUT.md` first |
25
+
26
+ **Precursor (optional but recommended):** If `docs/cms-guidelines/**` is stale or missing screenshots, run **`contentful-cms-update-cms-guidelines`** (`sync` or `fresh`) **before** playbooks so `components-index` and guideline snippets are accurate.
27
+
28
+ ## Pit-of-success order
29
+
30
+ 1. **Locate** customer repo + `cms-edit/<site>/project.json` → note `projectKey`, `appDir`
31
+ 2. **Audit** routing, page inventory, capabilities (Phase 1)
32
+ 3. **Plan** playbook set by tier (Phase 2) — propose to user before writing P1/P2
33
+ 4. **Write** playbooks + task stubs (Phase 3)
34
+ 5. **Regenerate** editor pack + doctor (Phase 4) — skill **`contentful-cms-regenerate-editor-pack`**
35
+ 6. **Commit + push** customer `develop` (never manual Vercel deploy)
36
+
37
+ Editors consume playbooks via skill **`contentful-cms-editor-tasks`** (`tasks-index` → `task-*` → specialized playbook).
38
+
39
+ ## Phase 1 — Site audit
40
+
41
+ Run from the **customer repo root**. Record findings in your working notes before writing files.
42
+
43
+ ### Config and routing
44
+
45
+ ```bash
46
+ # projectKey must match docs/cms-editor/<projectKey>/
47
+ cat cms-edit/<site>/project.json # or cms-edit/project.json (single-site)
48
+
49
+ # Routing flags and URL bases
50
+ cat <appDir>/src/lib/constants.ts
51
+ ```
52
+
53
+ Check:
54
+
55
+ | Signal | Source | Playbook impact |
56
+ |--------|--------|-----------------|
57
+ | `projectKey` | `project.json` | Directory name under `docs/cms-editor/` |
58
+ | `enablePerson` | `constants.ts` | `people.md` when true (doctor warns if missing) |
59
+ | `enableArticleTypeIndex` / article routes | `constants.ts` | `articles.md` depth |
60
+ | `ARTICLES_BASE`, `TAGS_BASE`, `PEOPLE_BASE` | `constants.ts` | URL patterns in playbooks |
61
+ | `homepageSlug` | `project.json` `website` (default `index`) | Routing examples |
62
+ | `markdownArticleTypeSlugs` | `constants.ts` | Article URL shapes (Pedestal) |
63
+
64
+ ### Page inventory
65
+
66
+ Build a **category table** (URL prefix → human label → clone reference slug):
67
+
68
+ 1. Production sitemap: `curl -s https://<prod>/sitemap.xml` or app's `pnpm sitemap-validate` config
69
+ 2. Group paths by prefix (`/resources/`, `/insights/`, `/what-we-treat/`, etc.)
70
+ 3. Pick 1–3 **canonical clone sources** per category (`peek --page-slug`, live `.md` URLs)
71
+
72
+ ### CMS capabilities
73
+
74
+ With dev server + tokens in `.env.local`:
75
+
76
+ ```bash
77
+ cms-edit project validate --project-config cms-edit/<site>/project.json
78
+ cms-edit editor-pack generate --project-config cms-edit/<site>/project.json # dry run if pack exists
79
+ cms-edit list --type template
80
+ cms-edit peek --page-slug /about # adjust per site
81
+ ```
82
+
83
+ Read generated `capabilities.json` (or editor-pack copy) for `content.pages`, `content.articles`, `content.persons`.
84
+
85
+ ### Skip rules
86
+
87
+ | Condition | Skip |
88
+ |-----------|------|
89
+ | `enablePerson === false` | `people.md` (SE website — team via **Person** entries in collections, not `/people/` routes) |
90
+ | No distinct URL category with ≥3 pages | Specialized playbook — fold into `pages.md` |
91
+ | Page type is engineering-only | Document in `pages.md` "out of scope" instead |
92
+
93
+ ## Phase 2 — Plan playbook tiers
94
+
95
+ Propose a tier list to the user. Ship **P0 first**, regen + doctor, then P1/P2 in follow-up commits.
96
+
97
+ ### P0 (always aim to ship first)
98
+
99
+ | File | When |
100
+ |------|------|
101
+ | `pages.md` | Site has `content.pages` — **required** (doctor + checklist) |
102
+ | `articles.md` or `ARTICLES.md` | Site has articles — either filename works |
103
+ | `people.md` | `enablePerson === true` |
104
+ | 1–3 **specialized** playbooks | Highest editor traffic (see `PROJECT-ROLLOUT.md` per site) |
105
+
106
+ ### P1 — Secondary page families
107
+
108
+ Specialized playbooks for distinct URL families (provider, location, resources hub, bilingual locale, etc.).
109
+
110
+ ### P2 — Low-frequency / compliance
111
+
112
+ Legal/policy, niche hub indexes, partner microsites.
113
+
114
+ ### `pages.md` as hub
115
+
116
+ The general `pages.md` must link to every specialized playbook:
117
+
118
+ ```markdown
119
+ | Page type | Playbook |
120
+ |-----------|----------|
121
+ | Condition or therapy program | `cms-edit://customer/condition-program-pages` |
122
+ ```
123
+
124
+ See `PATTERNS.md` for the full Brightline hub example.
125
+
126
+ ## Phase 3 — Write playbooks
127
+
128
+ **Authoring path:** `docs/cms-editor/<projectKey>/`
129
+
130
+ ### File types
131
+
132
+ | Path | Becomes | Notes |
133
+ |------|---------|-------|
134
+ | `pages.md` | `cms-edit://customer/pages` | Sets `hasPagesPlaybook`; checklist auto-links |
135
+ | `articles.md` or `ARTICLES.md` | `cms-edit://customer/articles` | Special-cased in generator |
136
+ | `people.md` | `cms-edit://customer/people` | When persons enabled |
137
+ | `<topic>.md` | `cms-edit://customer/<topic>` | kebab-case basename = resource name |
138
+ | `tasks/<slug>.md` | `cms-edit://customer/task-<slug>` | Appears in `tasks-index` |
139
+
140
+ **Do not** put task stubs in the root — only under `tasks/`.
141
+
142
+ ### Specialized playbook sections
143
+
144
+ Each `<topic>.md` should include:
145
+
146
+ 1. **Title** — `# <Human name> — <Site>`
147
+ 2. **URL patterns** — table with examples
148
+ 3. **Typical content stack** — component/collection order
149
+ 4. **Reference pages** — clone sources with public paths
150
+ 5. **Template** — which Contentful template label
151
+ 6. **Workflow** — numbered steps ending in preview → diff → save → publish handoff
152
+ 7. **Out of scope** — what editors must not do
153
+
154
+ Start from template: `packages/contentful-cms/docs/cms-edit-project-template/docs/cms-editor/example/pages.md`
155
+
156
+ ### Task stub (required for tasks-index)
157
+
158
+ For each specialized playbook, add `tasks/<topic>.md`:
159
+
160
+ ```markdown
161
+ # Capability: <Short title>
162
+
163
+ ## Intent phrases
164
+
165
+ - <phrase editors might say>
166
+ - ...
167
+
168
+ ## Requires capabilities
169
+
170
+ `pages` # or `articles`, `persons`
171
+
172
+ ## Prerequisites
173
+
174
+ - Read `cms-edit://customer/<topic>`
175
+ - Read `cms-edit://customer/pages`
176
+
177
+ ## Steps
178
+
179
+ 1. ...
180
+ ```
181
+
182
+ Parser reads `# Capability:` title and `## Intent phrases` bullets for `tasks-index.md`. See `PATTERNS.md`.
183
+
184
+ ### SE website constraint
185
+
186
+ `se-website-2026` is **not** a free-form marketing site. Playbooks must:
187
+
188
+ - Emphasize **clone from reference pages** (`/index`, `/about`, `/services`, `/demo-landing`)
189
+ - Document **General Page** template + `topContent` / `content` regions (existing `pages.md`)
190
+ - Treat new page types as **exceptions** — flag component gaps, use **Generic** fallback
191
+ - **No** `people.md` — `enablePerson=false`; team content is **Person** entries inside **Team grid**
192
+ - Article playbooks cover work/video/blog — not arbitrary landing pages
193
+
194
+ Read existing `docs/cms-editor/se2026/pages.md` before extending; prefer tightening scope over adding many specialized playbooks.
195
+
196
+ ## Phase 4 — Regenerate and validate
197
+
198
+ Follow **`contentful-cms-regenerate-editor-pack`**:
199
+
200
+ ```bash
201
+ cms-edit project validate --project-config cms-edit/<site>/project.json
202
+ cms-edit editor-pack generate --project-config cms-edit/<site>/project.json
203
+ cms-edit project doctor --project-config cms-edit/<site>/project.json
204
+ ```
205
+
206
+ Doctor checks:
207
+
208
+ - `pages.md` present when pages capability on
209
+ - `articles.md` when articles capability on
210
+ - `people.md` when persons capability on
211
+ - Editor-pack resources match hand-authored files
212
+
213
+ Review diff:
214
+
215
+ - `tasks-index.md` lists new `task-*` entries with intent phrases
216
+ - `checklist.md` links `pages` / `articles` playbooks
217
+ - `manifest.json` includes new resource names
218
+ - `overview.md` references new playbooks
219
+
220
+ ## Phase 5 — Commit and publish
221
+
222
+ In the **customer repo** (not se-core-product):
223
+
224
+ ```bash
225
+ git add docs/cms-editor/<projectKey>/ cms-edit/<site>/editor-pack/
226
+ git commit -m "docs(cms-editor): add <site> editor playbooks (P0)"
227
+ git push origin develop
228
+ ```
229
+
230
+ Hosted MCP rebuilds from git push — **do not** run `vercel deploy` or `cms-edit:deploy`.
231
+
232
+ ## Multi-site monorepos
233
+
234
+ | Repo | Sites | `projectKey` folders |
235
+ |------|-------|----------------------|
236
+ | `pedestal-sites` | Pedestal Health, Headwater | `pedestal-health`, `headwater-science` |
237
+ | `brightline-sites` | Brightline, BLK | `brightline`, `brightlifekids` |
238
+
239
+ Each site has its own `cms-edit/<site>/project.json` and `docs/cms-editor/<projectKey>/`. Roll out **one site at a time**.
240
+
241
+ ## Suggested rollout queue
242
+
243
+ See **`PROJECT-ROLLOUT.md`** for per-site P0/P1/P2 checklists. Default order:
244
+
245
+ 1. **Pedestal** (`pedestal-health`, then `headwater-science`)
246
+ 2. **OM1**
247
+ 3. **PointMe**
248
+ 4. **SE website** (`se2026`) — hardest; extend existing playbooks cautiously
249
+
250
+ ## Related skills
251
+
252
+ | Skill | When |
253
+ |-------|------|
254
+ | `contentful-cms-regenerate-editor-pack` | After any playbook change |
255
+ | `contentful-cms-editor-tasks` | How editors consume playbooks |
256
+ | `contentful-cms-update-cms-guidelines` | Refresh guidelines/screenshots first |
257
+ | `contentful-cms-core` | `peek`, `list`, `create from-json` during audit |
258
+ | `se-marketing-sites-curate-showcase-mocks` | Showcase data before screenshot refresh |
259
+
260
+ ## Related docs
261
+
262
+ | Doc | Purpose |
263
+ |-----|---------|
264
+ | `docs/RELATED_PROJECTS.md` | Repo paths, Contentful spaces |
265
+ | `packages/contentful-cms/docs/cms-edit-project-template/README.md` | `project.json`, playbook stubs |
266
+ | `packages/contentful-cms/docs/mcp/hosted-guide.md` | MCP resource URIs |
@@ -28,9 +28,9 @@ The playbook defines phases, hosted vs local limits, and confirmation gates. Thi
28
28
 
29
29
  | Goal | Command |
30
30
  |------|---------|
31
- | Failures JSON | `cms-edit --json asset review` |
32
- | Full + usage (local) | `cms-edit --json asset review --include-passing --include-usage --usage-limit 0` |
33
- | Usage sample (hosted) | `cms-edit --json asset review --include-usage --usage-limit 50` |
31
+ | Failures JSON | `cms-edit --json-output asset review` |
32
+ | Full + usage (local) | `cms-edit --json-output asset review --include-passing --include-usage --usage-limit 0` |
33
+ | Usage sample (hosted) | `cms-edit --json-output asset review --include-usage --usage-limit 50` |
34
34
 
35
35
  Hosted MCP: **no `--space`**. Do not use `--usage-limit 0` with `--include-passing` on hosted MCP.
36
36
 
@@ -75,6 +75,8 @@ Summarize: totals, top `issueCounts`, quick wins (alt, GIFs, stock filenames).
75
75
 
76
76
  **Fixes (user-approved only):** `cms-edit asset set-description <id> "…"` — drafts only, no publish.
77
77
 
78
+ **Media entry labels:** The Contentful list label for a **Media** wrapper is its `name` field — **set it to the linked asset's `title`**, not `visual-{assetId}`, `Wrapper for {assetId}`, or the filename. When creating wrappers: `cms-edit create media --asset-id <id>` (name defaults to asset title) or `asset upload --with-media` (use `--media-name` only when you need a distinct label for multiple wrappers on the same asset). To fix existing entries: `cms-edit batch set <media-entry-id>:name=<asset-title>` then `batch save`.
79
+
78
80
  For per-page alt work: **`contentful-cms-alt-text-audit`**.
79
81
 
80
82
  ## Image guide (optional extension)
@@ -82,7 +84,7 @@ For per-page alt work: **`contentful-cms-alt-text-audit`**.
82
84
  When the client wants a **reference guide** (not just remediation):
83
85
 
84
86
  ```bash
85
- cms-edit --json asset review --include-passing --include-usage --usage-limit 0 > docs/image-inventory.json
87
+ cms-edit --json-output asset review --include-passing --include-usage --usage-limit 0 > docs/image-inventory.json
86
88
  ```
87
89
 
88
90
  - Cache AI descriptions: `docs/descriptions/{assetId}.json` (write-through per image)
@@ -125,6 +125,7 @@ In Claude Desktop (hosted integration): ask to read `cms-edit://customer/routing
125
125
 
126
126
  | Prior work | Skill |
127
127
  |------------|-------|
128
+ | New hand-authored playbooks | `contentful-cms-create-editor-playbooks` |
128
129
  | Guidelines changed | `contentful-cms-update-cms-guidelines` |
129
130
  | New registration | `se-marketing-sites-register-cms-features` |
130
131
  | Editor Integrations setup | `contentful-cms-setup` (hosted path) |
@@ -10,11 +10,11 @@ Use this skill when editing **rich text** fields (body, additionalCopy) and inse
10
10
  ## Rich text (rtf)
11
11
 
12
12
  - **Replace** body with Markdown (single paragraph, no newlines): `cms-edit rtf @c1 body --markdown "Simple body with **bold** and [link](https://example.com)."`
13
- - **Multiline content** — use `printf` piped to stdin; `\n` in a double-quoted shell string is **not** a newline in bash:
13
+ - **Multiline content** — use `--content` or `--base64` (hosted MCP has no filesystem):
14
14
  ```bash
15
- printf '## Heading\n\nParagraph with **bold** and [link](https://example.com).\n' | cms-edit rtf @c1 body --markdown -
15
+ cms-edit rtf @c1 body --markdown --content "## Heading\n\nParagraph with **bold**."
16
16
  ```
17
- - Use `--file path/to/file.md` or stdin (`-`) for long content.
17
+ - For large payloads via MCP: `--base64 <encoded-markdown>`.
18
18
  - Markdown supported: headings, bold/italic, links, lists, blockquote, inline code, `---`.
19
19
 
20
20
  Use **set** for scalar and link fields; use **rtf** only for rich text fields.
@@ -56,11 +56,8 @@ cms-edit rtf replace @c1 body \
56
56
  Apply multiple find/replace operations in a single call. All ops are validated before any write.
57
57
 
58
58
  ```bash
59
- # From file
60
- cms-edit rtf patch @c0 body --file patch.json
61
-
62
- # From stdin
63
- echo '[{"find":"old","replaceWith":"new","mode":"exactlyOne"}]' | cms-edit rtf patch @c0 body
59
+ cms-edit rtf patch @c0 body --json '[{"find":"old","replaceWith":"new","mode":"exactlyOne"}]'
60
+ # Or --json-base64 for large patch arrays
64
61
  ```
65
62
 
66
63
  Each op in the JSON array supports:
@@ -25,8 +25,8 @@ If no brand context is available, ask the user for these details.
25
25
  | About | AboutPage + Organization |
26
26
  | Service/Product | Service or Product |
27
27
  | Pricing | Product with Offer |
28
- | Blog listing | CollectionPage |
29
- | Article | Article or BlogPosting |
28
+ | Blog listing | CollectionPage + Blog + ItemList |
29
+ | Article | BlogPosting |
30
30
  | FAQ | FAQPage with Question/Answer |
31
31
  | Contact | ContactPage |
32
32
  | Team/People | ProfilePage or Person |
@@ -35,33 +35,59 @@ If no brand context is available, ask the user for these details.
35
35
 
36
36
  ## Phase 2: Generate Mustache Templates
37
37
 
38
- Create JSON-LD templates using these standard Mustache variables:
38
+ Create JSON-LD templates using runtime variables from `buildStructuredDataContext()` in `@se-studio/core-ui` (see `packages/core-ui/src/utils/structuredDataUtils.ts`).
39
39
 
40
- - `{{title}}` — page/article title
41
- - `{{seoDescription}}` — SEO meta description
42
- - `{{slug}}` — page slug
43
- - `{{publishDate}}` — article publish date
44
- - `{{updatedAt}}` — last modification date
45
- - `{{authorName}}` — primary article author name (first in `authors`)
46
- - `{{#article.authors}}` — multi-author JSON-LD (`name`, `url` per author)
47
- - `{{heroImageUrl}}` — primary image URL
48
- - `{{customerName}}` — from brand context
49
- - `{{siteUrl}}` — from brand context
40
+ Reference markup generators in `@se-studio/cms-seo` (`breadcrumbListMarkup`, `blogPostingMarkup`, `itemListMarkup`, etc.).
41
+
42
+ ### URLs and page
43
+
44
+ - `{{baseUrl}}` — site origin with trailing slash (e.g. `https://www.example.com/`)
45
+ - `{{{baseUrl}}}` — same, triple-brace for JSON-safe URLs in `@id` fields
46
+ - `{{currentUrl}}` / `{{{currentUrl}}}` — full canonical URL of the current page
47
+ - `{{page.title}}` — page or content title
48
+ - `{{page.description}}` — SEO meta description
49
+ - `{{page.slug}}` — content slug
50
+ - `{{{page.imageUrl}}}` — OG image URL when featured image is set
51
+ - `{{#page.breadcrumbs}}` — breadcrumb segments: `position`, `name`, optional `url`, `last`
52
+
53
+ ### Articles
54
+
55
+ - `{{article.title}}`, `{{article.description}}`
56
+ - `{{article.datePublished}}`, `{{article.dateModified}}` — ISO 8601 (not `article.date`)
57
+ - `{{article.authorName}}`, `{{{article.authorUrl}}}` — primary author
58
+ - `{{#article.authors}}` — multi-author: `name`, optional `url` per author
59
+ - `{{{article.imageUrl}}}` — featured image URL
60
+
61
+ ### Person pages
62
+
63
+ - `{{person.name}}`, `{{person.jobTitle}}`, `{{{person.imageUrl}}}`
64
+
65
+ ### Listing pages (ItemList)
66
+
67
+ When the app wires `buildListingItems()` / `buildListingStructuredDataContext()` from `@se-studio/core-ui/server`:
68
+
69
+ - `{{#listing.items}}` — `position`, `name`, `{{{url}}}`, `last` (for Mustache comma separation)
70
+
71
+ Static brand data (organization address, social URLs, logo) belongs **in the CMS template**, not in code.
50
72
 
51
73
  ## Phase 3: Upload via cms-edit
52
74
 
53
75
  1. Check available fields:
54
76
  - `cms-edit schema page` — page content type fields
55
77
  - `cms-edit schema template` — template content type fields
56
- - Look for `schemaOrg`, `jsonLd`, `structuredData`, or similar
57
- 2. For **template-level** schemas (Organization, WebSite — shared): `cms-edit list --type template` → open → set
58
- 3. For **page-level** schemas: open each page → set its schema field
59
- 4. `cms-edit diff` then `cms-edit save`
78
+ - Look for `structuredData` or `indexPageStructuredData`
79
+ 2. For **template-level** schemas (Organization, WebSite, BreadcrumbList — shared): `cms-edit list --type template` → open → set
80
+ 3. For **article type** schemas (BlogPosting on `structuredData`, Blog/CollectionPage/ItemList on `indexPageStructuredData`): link on articleType entry
81
+ 4. For **page-level** subtype overrides (FAQPage, Product, Service): link on the page entry only
82
+ 5. `cms-edit diff` then `cms-edit save`
60
83
 
61
84
  ## Best Practices
62
85
 
63
86
  - Don't duplicate — template-level Organization schema covers all pages
64
- - Use specific types — `MedicalBusiness` over `LocalBusiness` if applicable
87
+ - Link schema on **templates and types**, not on every article
88
+ - Use specific types where they apply — `BlogPosting` for blog posts, `ProfilePage` for authors
89
+ - BreadcrumbList `item` property: output only when `{{#url}}` is present on a segment
90
+ - One FAQPage per URL — do not duplicate component-level and CMS-level FAQPage on the same page
65
91
  - Validate all required properties are present
66
92
  - Schema must reflect actual page content
67
93
 
@@ -72,4 +98,4 @@ Create JSON-LD templates using these standard Mustache variables:
72
98
 
73
99
  ## Related skills
74
100
 
75
- See the **core** skill for the full cms-edit workflow. See the **seo-descriptions** skill for meta description generation. For bulk audit/apply across all entries, schema linking, publish phases, and production verification, see **cms-seo-audit**.
101
+ See the **core** skill for the full cms-edit workflow. See the **seo-descriptions** skill for meta description generation. For bulk audit/apply across all entries, schema linking, publish phases, and production verification, see **cms-seo-audit**.
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  name: contentful-cms-setup
3
- description: "Guide a user through connecting hosted cms-edit MCP for Claude (Integrations + OAuth)."
3
+ description: "Guide a user through connecting hosted cms-edit MCP for Claude or Grok (OAuth)."
4
4
  ---
5
5
 
6
6
  # Skill: cms-edit Setup
7
7
 
8
- Use this skill when the user wants to connect Claude to their Contentful site via **hosted cms-edit MCP**.
8
+ Use this skill when the user wants to connect Claude or Grok to their Contentful site via **hosted cms-edit MCP**.
9
9
 
10
10
  Local stdio MCP and the setup wizard are **not supported**. Editors connect through the site's `/cms-edit` onboarding flow.
11
11
 
@@ -35,6 +35,39 @@ Use skill **`contentful-cms-editor-tasks`** for the tasks-index → capability p
35
35
 
36
36
  ---
37
37
 
38
+ ## Hosted setup (Grok Build)
39
+
40
+ Use when the user wants cms-edit in **Grok Build** (not local stdio MCP).
41
+
42
+ ### Step 1: Configure Grok
43
+
44
+ Add to `~/.grok/config.toml`:
45
+
46
+ ```toml
47
+ [mcp_servers.cms-edit-<projectKey>]
48
+ url = "https://<host>/api/mcp"
49
+ enabled = true
50
+ ```
51
+
52
+ The URL **must** end with `/api/mcp`. Use the MCP URL from the site's `/cms-edit` page.
53
+
54
+ ### Step 2: Connect
55
+
56
+ 1. In Grok, run `/mcps`
57
+ 2. Select the cms-edit server
58
+ 3. Press **`i`** to initiate OAuth (not just enable)
59
+ 4. Sign in with Contentful when prompted
60
+
61
+ ### Step 3: Verify
62
+
63
+ Run `grok mcp doctor cms-edit-<projectKey>` or call `cms_edit_version` in a Grok session.
64
+
65
+ **Reconnect:** `/mcps` → press `i` again if OAuth expires.
66
+
67
+ Full guide: `packages/contentful-cms/docs/mcp/hosted-guide.md` (Grok Build section).
68
+
69
+ ---
70
+
38
71
  ## Developers (CLI + skills, not local MCP)
39
72
 
40
73
  For engineering work in a site repo (Cursor, Grok, terminal):
@@ -51,7 +84,10 @@ Do **not** register a local `mcpServers.cms-edit` entry in Claude Desktop — us
51
84
  ## Troubleshooting
52
85
 
53
86
  **OAuth / sign-in fails**
54
- → Confirm the user was invited to the Contentful space and is signing in with the correct account.
87
+ → Confirm the user was invited to the Contentful space and is signing in with the correct account. In Grok, use `/mcps` → press `i` (not just toggle). Confirm config URL ends with `/api/mcp`.
88
+
89
+ **Grok browser flashes and closes**
90
+ → Usually a redirect_uri mismatch before cms-edit v2.7.7+; upgrade the hosted deployment and retry OAuth.
55
91
 
56
92
  **`cms_edit` tool not available**
57
93
  → Reconnect via `/cms-edit` or Claude Integrations. Remove any legacy local MCP or `.mcpb` extension entries.
@@ -0,0 +1,69 @@
1
+ ---
2
+ name: se-marketing-sites-markdown-accuracy-review
3
+ description: "LLM review of production markdown exports vs HTML pages. Use when auditing .md accuracy, running markdown-accuracy-audit artifacts, or writing docs/reports/markdown-accuracy-audit.md."
4
+ ---
5
+
6
+ # Markdown accuracy review (LLM)
7
+
8
+ Compare production **HTML** pages with their **`.md`** exports to judge whether markdown is an accurate representation of CMS content. Metrics collection is automated; **verdicts are written by the agent** using this rubric.
9
+
10
+ ## Prerequisites
11
+
12
+ 1. Run the collector from monorepo root:
13
+
14
+ ```bash
15
+ node packages/site-check/markdown-accuracy-audit.mjs --site se2026 --path /about/ --dry-run
16
+ node packages/site-check/markdown-accuracy-audit.mjs --delay-ms 500
17
+ ```
18
+
19
+ 2. Read artifacts under `docs/reports/.markdown-audit-artifacts/<site>/<slug>/`:
20
+ - `meta.json` — URLs, metrics, cache headers
21
+ - `page.html` — full HTML (`<script>` / `<style>` removed only)
22
+ - `page.md` — full markdown, verbatim
23
+
24
+ **Do not truncate** HTML or markdown when reviewing. Read complete files.
25
+
26
+ ## Review rubric
27
+
28
+ For each URL, assess:
29
+
30
+ | Dimension | Question |
31
+ |-----------|----------|
32
+ | **Coverage** | Are substantive CMS blocks (headings, body, lists, link text, image alt text) present in markdown? |
33
+ | **Fidelity** | Do title, H1, and key facts match HTML? Any wrong or invented content? |
34
+ | **Expected omissions** | Nav, footer, cookie banners, forms, carousels, video players, and interactive widgets may be absent — note explicitly. |
35
+ | **Markdown quality** | Sensible structure, working link hrefs, frontmatter completeness, canonical alignment. |
36
+ | **Fetch health** | Check `meta.json` metrics — non-2xx or empty bodies are `Error`, not content verdicts. |
37
+
38
+ ## Verdicts
39
+
40
+ Use exactly one:
41
+
42
+ - **Accurate** — CMS content fully represented; omissions are only expected chrome/interactivity.
43
+ - **Mostly accurate** — Core content matches; minor gaps (eyebrow text, secondary metadata, non-critical visuals).
44
+ - **Partial** — Important sections missing or materially different, but primary message partly preserved.
45
+ - **Inaccurate** — Wrong headings/facts, major missing blocks, or misleading representation.
46
+ - **Error** — Fetch failed or empty response (see `meta.json` metrics).
47
+
48
+ ## Review column format
49
+
50
+ 2–4 sentences in the final report table:
51
+
52
+ ```text
53
+ **Mostly accurate** — H1 and body copy match. Markdown omits the team photo grid and contact form (expected). Pre-heading eyebrow in HTML not exported.
54
+ ```
55
+
56
+ ## Report assembly
57
+
58
+ Write [`docs/reports/markdown-accuracy-audit.md`](../../../../docs/reports/markdown-accuracy-audit.md):
59
+
60
+ 1. Run metadata (timestamp, site count, URL count).
61
+ 2. Summary table of verdict counts.
62
+ 3. Per-site sections with table columns: **URL | HTML size | MD size | HTML ms | MD ms | Cache | Review**.
63
+ 4. JSON sidecar [`docs/reports/markdown-accuracy-audit.json`](../../../../docs/reports/markdown-accuracy-audit.json) merging metrics + verdict + review text.
64
+
65
+ Review in site batches (~6–13 URLs). Commit `.md` and `.json` to `dev`; artifacts dir stays gitignored.
66
+
67
+ ## Dry-run gate
68
+
69
+ When asked for a dry run, collect **one** case (default: SE Studio `/about/`), perform the LLM review, and present a **single sample table row** for format approval before running all 51 smoke URLs.
@@ -87,12 +87,28 @@ jobs:
87
87
  VERCEL_PROTECTION_BYPASS_TOKEN: ${{ secrets.VERCEL_PROTECTION_BYPASS_TOKEN }}
88
88
  run: pnpm smoke-test:live
89
89
  - name: Report Deployment Check status
90
- if: always()
91
- uses: vercel/repository-dispatch/actions/status@v1
90
+ if: always() && github.event_name == 'repository_dispatch'
91
+ uses: vercel/repository-dispatch/actions/status@44f4d342ebc265c58167a2aa77d5a0d5a6eb20fd
92
92
  with:
93
93
  name: "Vercel - <vercel-project-name>: deployment smoke"
94
+ # Vercel can miss the first GitHub status webhook; re-post after a short delay.
95
+ - name: Retry Deployment Check status for Vercel reconciliation
96
+ if: always() && github.event_name == 'repository_dispatch'
97
+ env:
98
+ CHECK_NAME: "Vercel - <vercel-project-name>: deployment smoke"
99
+ DEPLOYMENT_SHA: ${{ github.event.client_payload.git.sha }}
100
+ CHECK_STATE: ${{ job.status == 'success' && 'success' || 'failure' }}
101
+ GH_TOKEN: ${{ github.token }}
102
+ run: |
103
+ sleep 30
104
+ gh api "repos/${GITHUB_REPOSITORY}/statuses/${DEPLOYMENT_SHA}" \
105
+ -f state="${CHECK_STATE}" \
106
+ -f context="${CHECK_NAME}" \
107
+ -f target_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}"
94
108
  ```
95
109
 
110
+ Use the deployment commit SHA from `client_payload.git.sha`, not `github.sha`. Repeat the retry block in each job when a workflow has multiple Vercel projects (monorepos).
111
+
96
112
  GitHub secret: `VERCEL_PROTECTION_BYPASS_TOKEN` (Vercel → Deployment Protection → Protection Bypass for Automation). Set `SMOKE_TEST_IGNORE=true` to bypass smoke in an emergency.
97
113
 
98
114
  Or from the app directory without a per-app script: `node ../../scripts/smoke-test-preview.mjs` (loads `.env.local` and calls `runPreviewStaticSmokeTest`).
@@ -11,7 +11,7 @@ Update npm dependencies to **latest** in se-core-product and consumer repos that
11
11
 
12
12
  **Default:** Process **one repo per invocation**. At the end, summarize changes and offer the next project.
13
13
 
14
- **Never:** push to `main`/`master`; bump Next to 16; bump Node to 25+; use `pnpm patch` / `patchedDependencies` / `patches/`.
14
+ **Never:** push to `main`/`master`; bump Next to 16; bump Node to 25+; use `pnpm patch` / `patchedDependencies` / `patches/`; bypass or remove `minimumReleaseAge`.
15
15
 
16
16
  ---
17
17
 
@@ -61,17 +61,27 @@ Commit the bootstrap copy as part of the deps update commit when you add it.
61
61
 
62
62
  ---
63
63
 
64
- ## Step 3 — Pin overrides (before `--latest`)
64
+ ## Step 3 — Supply-chain policy + pin overrides
65
65
 
66
- `pnpm update -r --latest` would bump `next` → 16 and `@types/node` → 26. Add or verify this block in `pnpm-workspace.yaml` (values from registry `pinOverrides`):
66
+ Every repo **must** have this block in `pnpm-workspace.yaml` (merge into existing file — do not remove other keys such as `allowBuilds`, repo-specific excludes, or PointMe's extra overrides):
67
67
 
68
68
  ```yaml
69
+ minimumReleaseAge: 1440
70
+ minimumReleaseAgeExclude:
71
+ - '@se-studio/*'
72
+
69
73
  overrides:
70
74
  next: ^15.5.19
71
75
  '@types/node': ^24.13.2
72
76
  ```
73
77
 
74
- Skip if `hasPinOverrides` is already true and values match. Idempotent — merge into existing `pnpm-workspace.yaml` without removing other keys (`minimumReleaseAge`, `allowBuilds`, etc.).
78
+ - **`minimumReleaseAge: 1440`** — do not install packages published in the last 24 hours (supply-chain guard).
79
+ - **`@se-studio/*` exclude** — our own packages may update immediately after npm publish.
80
+ - **Keep repo-specific additional excludes** when present (e.g. vitest pins in se-core-product, `@emnapi/runtime` in se-website-2026, PointMe `mapbox-gl` / `react-day-picker` overrides).
81
+
82
+ `pnpm update -r --latest` would bump `next` → 16 and `@types/node` → 26 without the overrides block. The overrides prevent that.
83
+
84
+ **Never bypass `minimumReleaseAge`** during dependency updates. Do not remove the block, comment it out, or use undocumented pnpm flags. If a non-`@se-studio` package was published within 24 hours, it stays at the current version until it ages out — note that in the report and re-run later if needed.
75
85
 
76
86
  ---
77
87
 
@@ -80,14 +90,15 @@ Skip if `hasPinOverrides` is already true and values match. Idempotent — merge
80
90
  Bump the package manager to the **latest pnpm 11.x** in root `package.json`:
81
91
 
82
92
  ```bash
83
- LATEST_PNPM=$(npm view pnpm@11 version)
84
- # Set "packageManager": "pnpm@<LATEST_PNPM>" in package.json
85
- corepack use pnpm@${LATEST_PNPM}
93
+ corepack use pnpm@11.9.0
94
+ # Or: LATEST=$(npm view pnpm@11.9.0 version) && corepack use pnpm@${LATEST}
86
95
  pnpm -v # confirm matches packageManager
87
96
  ```
88
97
 
89
98
  Keep `engines.pnpm` at `11.x` (do not jump to pnpm 12). If `engines.pnpm` is missing, add `"pnpm": "11.x"` alongside `"node": "24.x"`.
90
99
 
100
+ Align nested `packageManager` fields (e.g. `apps/*/package.json`) with the root version when validate fails on a version mismatch.
101
+
91
102
  ---
92
103
 
93
104
  ## Step 5 — Update dependencies
@@ -96,12 +107,26 @@ Keep `engines.pnpm` at `11.x` (do not jump to pnpm 12). If `engines.pnpm` is mis
96
107
  pnpm update -r --latest
97
108
  ```
98
109
 
99
- If brightline or pedestal repos block fresh packages (`minimumReleaseAge: 1440`), retry with:
110
+ Then explicitly align `@se-studio/*` where the repo uses them (omit packages the repo does not depend on):
100
111
 
101
112
  ```bash
102
- pnpm update -r --latest --no-minimum-release-age
113
+ pnpm update -r \
114
+ @se-studio/ab-testing \
115
+ @se-studio/cms-seo \
116
+ @se-studio/contentful-cms@^3.0.1 \
117
+ @se-studio/contentful-rest-api \
118
+ @se-studio/core-data-types \
119
+ @se-studio/core-ui \
120
+ @se-studio/hubspot \
121
+ @se-studio/markdown-renderer \
122
+ @se-studio/project-build \
123
+ @se-studio/search \
124
+ @se-studio/site-check \
125
+ @se-studio/skills
103
126
  ```
104
127
 
128
+ `@se-studio/*` resolves immediately via `minimumReleaseAgeExclude`. Other packages respect the 24-hour window.
129
+
105
130
  Safety re-pin after update:
106
131
 
107
132
  ```bash
@@ -155,6 +180,8 @@ Include in the summary:
155
180
  - Major dependency bumps (from the Step 1 audit diff)
156
181
  - pnpm version: before → after
157
182
  - Confirmed pins: Next 15.x, Node 24, `@types/node` ^24
183
+ - Confirmed `minimumReleaseAge: 1440` and `@se-studio/*` exclude present
184
+ - Packages still outdated because they are inside the 24-hour release window (if any)
158
185
  - Patches check bootstrapped (yes/no)
159
186
  - Remaining projects not yet updated
160
187
 
@@ -179,6 +206,7 @@ This is optional follow-up — the skill workflow always runs the check regardle
179
206
  | Issue | Action |
180
207
  |-------|--------|
181
208
  | `next` or `@types/node` still outdated to wrong major | Re-run overrides + safety re-pin; check `pnpm-workspace.yaml` overrides |
209
+ | Non-`@se-studio` package still outdated after update | Likely within 24h of npm publish — wait and re-run; **do not** bypass `minimumReleaseAge` |
182
210
  | `corepack use` fails | Run `corepack enable` once, retry |
183
211
  | Validate fails after major bump | Check breaking-change release notes; fix or revert |
184
212
  | Repo path missing | Skip; note in report — see `docs/RELATED_PROJECTS.md` |