@se-studio/skills 1.7.16 → 1.8.0

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.8.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 104ce64: Add `cms-edit patterns generate` to census published page and article stacks from the Delivery API, ship them as `page-patterns` in the editor pack, and teach editor skills to read families before cloning.
8
+
9
+ ## 1.7.17
10
+
11
+ ### Patch Changes
12
+
13
+ - 6fbdfd6: cms-edit media intake: stop teaching raster `asset upload`, surface staged GET 405 as a host bump (not a retry/UI fallback), and document the SE Studio local media loop.
14
+
3
15
  ## 1.7.16
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.7.16",
3
+ "version": "1.8.0",
4
4
  "description": "SE Studio agent skills for marketing site development with Contentful CMS",
5
5
  "repository": {
6
6
  "type": "git",
@@ -91,6 +91,8 @@ Brightline excerpt:
91
91
 
92
92
  Fetch live markdown when `website.markdownAccess` is enabled: `https://<prod><path>.md`
93
93
 
94
+ **Typical content stack** must match `page-patterns` (required types + clone slug). Shared blocks listed there are **edit in place** — do not fork. Nested families in `page-patterns` (child URL prefixes) need their own playbook, not one parent stack.
95
+
94
96
  ## Tier system (Brightline)
95
97
 
96
98
  ### P0 — ship first
@@ -150,6 +152,7 @@ Site `articles.md` must name **this site’s** body components. Do not paste SE
150
152
  | `people.md` | `enablePerson=true` — team profiles, author import |
151
153
  | `blog-tag-matrix.md` | Complex tag governance (Brightline) |
152
154
  | `site-facts.json` | Canonical support email, phone — becomes `site-facts` resource |
155
+ | `page-patterns.json` / `page-patterns.md` | Live Delivery census (`cms-edit patterns generate`) — clone slugs, stacks, shared blocks |
153
156
  | `tasks/*.md` only | Overrides for core tasks (e.g. `import-blog-tag-matrix`) |
154
157
  | `case-study-from-package.md` (SE) | Optional specialized multi-block package playbook + hosted example |
155
158
 
@@ -7,7 +7,9 @@ description: "Edit Contentful drafts via hosted cms-edit MCP (open → snapshot
7
7
 
8
8
  Use this skill when you need to read or edit content in Contentful using **hosted cms-edit MCP** (`cms_edit` with an `args` array). Command names match the old CLI (`open` → `snapshot` → `read` → `set`/`rtf` → `diff` → `save`).
9
9
 
10
- **Do not** run the local `cms-edit` binary for content. It refuses `open`, `save`, `set`, and other content commands. Local CLI is only for `host`, `editor-pack`, `project`, `schema`, and `guide`.
10
+ **Do not** run the local `cms-edit` binary for content. It refuses `open`, `save`, `set`, and other content commands. Local CLI is only for `host`, `editor-pack`, `patterns`, `project`, `schema`, and `guide`.
11
+
12
+ **Page patterns (local):** `cms-edit patterns generate --project-config cms-edit/<site>/project.json` writes live family stacks from the Delivery API. Hosted agents read `cms-edit://customer/page-patterns` after editor-pack generate.
11
13
 
12
14
  **Before editing:** use skill **`contentful-cms-editor-tasks`** to read `tasks-index` and the matching capability playbook for this site (hosted MCP or local `cms-edit/<site>/editor-pack/`).
13
15
 
@@ -33,7 +35,7 @@ All `save` operations create **draft** versions. A human must review and publish
33
35
  **Assets:** Upload **is** supported (`asset upload`). Default workflow: **search and reuse** existing assets first (`index sync` → `asset search`). When uploading:
34
36
  - **Raster/video:** `cms_edit_request_staged_upload` → curl → `cms_edit_media` prepare (`stagedUploadIds`) → wait → catalog → import with real alt. Never `asset upload --staged/--url/--base64` for jpeg/png/webp/gif/mp4.
35
37
  - **SVG/PDF/Lottie:** `cms_edit_request_staged_upload` → curl → `asset upload --staged` (never `--base64`)
36
- - **HtmlComponent / large JSON:** `cms_edit_request_staged_upload` with `kind=text` or `kind=json` → curl → `set --staged`, `rtf --staged`, `create from-json --staged`, or `apply from-json --staged`. Hosted MCP rejects inline `--json`/`--content` over 8192 bytes.
38
+ - **HtmlComponent / large JSON:** `cms_edit_request_staged_upload` with `kind=text` or `kind=json` → curl → `set --staged`, `rtf --staged`, `create from-json --staged`, or `apply from-json --staged`. Hosted MCP rejects inline `--json`/`--content` over 8192 bytes. If the wrapper schema has no `kind`, use `cms_edit` `["staged-upload", "request", "--kind", "json", "--file-name", "...", "--mime", "application/json"]` (or `--kind text`), then curl, then `--staged`.
37
39
  - Use a **sensible fileName** and **descriptive title** (and alt text where the site uses it)
38
40
  - Avoid oversized images — width over **2000px** is usually wasteful for web (exact limits vary by project; check `asset audit` / media review guidance)
39
41
  - Prefer `--if-exists-by-filename` to avoid duplicates
@@ -374,11 +376,10 @@ cms-edit asset search --filename istockphoto-123.jpg
374
376
  cms-edit asset search --filename-match 'istockphoto-.*'
375
377
 
376
378
  # Raster/video: cms_edit_media prepare → wait → catalog → import (video: import only).
379
+ # Do not `asset upload` jpeg/png/webp/gif/mp4. Do not convert GIF/MP4 with local ffmpeg.
380
+ # Animated GIF: leave as GIF; pipeline emits gif-converted MP4 for Media mute-loop, not featuredImage.
377
381
  # SVG/PDF/Lottie: cms_edit_request_staged_upload → curl → asset upload --staged
378
382
 
379
- # Upload and create a Media wrapper in one step (--media-name defaults to asset title)
380
- cms-edit asset upload ./figure.png --with-media --media-position Middle
381
-
382
383
  # Create a Media wrapper for an existing asset (name defaults to asset title)
383
384
  cms-edit create media --asset-id <asset-id>
384
385
 
@@ -65,11 +65,20 @@ Check:
65
65
 
66
66
  ### Page inventory
67
67
 
68
- Build a **category table** (URL prefix → human label → clone reference slug):
68
+ Build the category table from **Delivery page-patterns**, not sitemap prefixes alone:
69
69
 
70
- 1. Production sitemap: `curl -s https://<prod>/sitemap.xml` or app's `pnpm sitemap-validate` config
71
- 2. Group paths by prefix (`/resources/`, `/insights/`, `/what-we-treat/`, etc.)
72
- 3. Pick 1–3 **canonical clone sources** per category (`peek --page-slug`, live `.md` URLs)
70
+ ```bash
71
+ cms-edit patterns generate --project-config cms-edit/<site>/project.json
72
+ # writes docs/cms-editor/<projectKey>/page-patterns.json + page-patterns.md
73
+ ```
74
+
75
+ 1. Read `page-patterns.md` — each **family** is a candidate playbook (including nested children)
76
+ 2. Use each family's `cloneSlug` as the canonical clone source
77
+ 3. Nested children (e.g. `what-we-treat/anxiety/types`) get their **own** specialized playbook
78
+ 4. Flags: `low-majority-campaign` / `unique-compositions` → document the skeleton and clone the nearest sibling; do **not** invent one canonical stack. `empty-body` article types are template-owned.
79
+ 5. Sitemap / `peek` only to confirm public URLs and copy, not to discover families
80
+
81
+ Requires `CONTENTFUL_ACCESS_TOKEN` (Delivery). If generate cannot run, say so and fall back to sitemap prefixes.
73
82
 
74
83
  ### CMS capabilities
75
84
 
@@ -86,10 +95,11 @@ Read generated `capabilities.json` (or editor-pack copy) for `content.pages`, `c
86
95
 
87
96
  ### Skip rules
88
97
 
89
- | Condition | Skip |
90
- |-----------|------|
91
- | `enablePerson === false` | `people.md` (SE website — team via **Person** entries in collections, not `/people/` routes) |
92
- | No distinct URL category with ≥3 pages | Specialized playbook — fold into `pages.md` |
98
+ | Condition | Action |
99
+ |-----------|--------|
100
+ | `enablePerson === false` | Skip `people.md` (SE website — team via **Person** entries in collections, not `/people/` routes) |
101
+ | Unique high-value hub (e.g. `/schools`) even if n=1 | Still document in `pages.md` with its live stack |
102
+ | No distinct URL family with ≥3 pages **and** no useful unique hub | Fold into `pages.md` — no specialized playbook |
93
103
  | Page type is engineering-only | Document in `pages.md` "out of scope" instead |
94
104
 
95
105
  ## Phase 2 — Plan playbook tiers
@@ -13,8 +13,9 @@ Use this skill **before any Contentful edit** to pick the right capability playb
13
13
  2. **capabilities** — what content types and bulk mechanisms exist
14
14
  3. **checklist** — pre-flight checks
15
15
  4. **overview** + **routing** — site rules and URL shapes
16
- 5. **task-*** playbook — steps, confirmation gates, out-of-scope
17
- 6. **components-index** — when creating or editing page content
16
+ 5. **page-patterns** — live slug/article-type families, clone slugs, shared blocks (`cms-edit://customer/page-patterns`)
17
+ 6. **task-*** playbook — steps, confirmation gates, out-of-scope
18
+ 7. **components-index** — when creating or editing page content
18
19
 
19
20
  ## Hosted (Claude Integrations + OAuth)
20
21
 
@@ -47,6 +48,7 @@ Minimum reads:
47
48
  - `capabilities.json`
48
49
  - `tasks-index.md`
49
50
  - `checklist.md`
51
+ - `page-patterns.md` (match the URL or article type to a family before clone)
50
52
  - Matching `task-*.md` for the user's intent
51
53
 
52
54
  Then use **`contentful-cms-core`** for `cms-edit` CLI commands.
@@ -62,6 +62,14 @@ pnpm cms-edit:editor-pack
62
62
 
63
63
  **Generic / multi-site:**
64
64
 
65
+ If Delivery credentials are in `.env.local` and `docs/cms-editor/<projectKey>/page-patterns.md` is missing or stale, refresh families first:
66
+
67
+ ```bash
68
+ cms-edit patterns generate --project-config cms-edit/<site>/project.json
69
+ ```
70
+
71
+ Then:
72
+
65
73
  ```bash
66
74
  cms-edit editor-pack generate --project-config cms-edit/<site>/project.json
67
75
  ```
@@ -40,34 +40,40 @@ import { Visual } from '@se-studio/core-ui';
40
40
  You **MUST** provide `visualSizes` to ensure the browser loads the correct image size. This uses the `sizes` attribute.
41
41
 
42
42
  ```typescript
43
- import { calculateVisualSizes } from '@se-studio/core-ui';
43
+ import { calculateVisualSizes, cardVisualSizes, heroVisualSizes } from '@se-studio/core-ui';
44
44
 
45
- // Example: Full width on mobile, 50% width on laptop
45
+ const heroSizes = heroVisualSizes(); // defaultSize 100vw; no breakpoints
46
+ const cardSizes = cardVisualSizes({ columns: 3, mobileColumns: 2 });
46
47
  const sizes = calculateVisualSizes(1, { laptop: 0.5 });
47
48
 
48
- <VisualComponent
49
- visual={visual}
50
- visualSizes={sizes}
51
- />
49
+ <VisualComponent visual={heroVisual} visualSizes={heroSizes} />
50
+ <VisualComponent visual={cardVisual} visualSizes={cardSizes} />
51
+ <VisualComponent visual={splitVisual} visualSizes={sizes} />
52
52
  ```
53
53
 
54
- * `1`: 100vw (Mobile default)
55
- * `laptop: 0.5`: 50vw (Laptop breakpoint)
54
+ * `heroVisualSizes()`: full-bleed — `defaultSize` `100vw`, no breakpoints (same as `calculateVisualSizes(1)`). `PictureComponent` keeps the full next/image srcset ladder.
55
+ * `cardVisualSizes({ columns, mobileColumns })`: mobile column vw; laptop `min(columnVw, capPx)`; desktop px cap `round(contentMax / columns)` (3-up → 480px at 1440). Match `columns` / `mobileColumns` to the real grid (example-empty LinkCard is 4-up). Capped sizes also bound the `/_next/image` srcset (384, 640, 828, 1080, plus one large ≤1504 already in the app config). Do not invent `w` values or shrink global `deviceSizes`.
56
+ * `calculateVisualSizes(1, { laptop: 0.5 })`: `1` = 100vw mobile; `laptop: 0.5` = 50vw. Callers stay vw-only (full srcset, not the card subset).
56
57
 
57
58
  ### visualSizes Must Mirror Col-Span
58
59
 
59
60
  `visualSizes` **must** match the visual's layout (col-span, container width). The browser uses these values to pick the right image size.
60
61
 
62
+ * **Card grids**: `cardVisualSizes({ columns, mobileColumns })` — use the actual column counts (e.g. 4-up `centered-grid-4` → `{ columns: 4, mobileColumns: 4 }`; 3-up with 2-up mobile → `{ columns: 3, mobileColumns: 2 }`).
63
+ * **Full-bleed / hero**: `heroVisualSizes()` or `calculateVisualSizes(1)`.
61
64
  * **Rule**: `col-span-N` in a 12-col grid → use `N/12` (e.g. 6 cols → 0.5, 5 cols → 5/12).
62
- * **Full width** (`col-span-full`) → use `1`.
63
- * **First arg** = mobile/default; breakpoint keys (`laptop`, `tablet`, `desktop`) = that breakpoint.
65
+ * **Full width** (`col-span-full`) → use `1` / `heroVisualSizes()`.
66
+ * **First arg** of `calculateVisualSizes` = mobile/default; breakpoint keys (`laptop`, `tablet`, `desktop`) = that breakpoint.
64
67
  * **Common mistake**: Reversing mobile vs laptop. If mobile is full width and laptop is smaller, use `(1, { laptop: 0.5 })`, **not** `(0.5, { laptop: 1 })`.
65
68
  * **Fixed-size icons** (~96–128px): use small ratios like `0.2`–`0.25`; **never** use values > 1 (e.g. `(100)` is invalid and causes massive over-fetch).
66
69
  * **Example table**:
67
70
 
68
71
  | Layout | visualSizes |
69
72
  |--------|-------------|
70
- | Full width | `(1)` |
73
+ | Full width / hero | `heroVisualSizes()` or `(1)` |
74
+ | 4-up cards (e.g. `centered-grid-4`) | `cardVisualSizes({ columns: 4, mobileColumns: 4 })` |
75
+ | 3-up cards (2-up mobile) | `cardVisualSizes({ columns: 3, mobileColumns: 2 })` |
76
+ | 2-up cards | `cardVisualSizes({ columns: 2 })` |
71
77
  | 6 cols on laptop, full on mobile | `(1, { laptop: 0.5 })` |
72
78
  | 5 cols on laptop, full on mobile | `(1, { laptop: 5/12 })` |
73
79
  | 2 cols in 12 on laptop, half on mobile | `(0.5, { laptop: 2/12 })` |