@se-studio/skills 1.7.11 → 1.7.13

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.7.13
4
+
5
+ ### Patch Changes
6
+
7
+ - Quote `coding-discipline` skill description so customer `skills:validate` accepts the published package.
8
+
9
+ ## 1.7.12
10
+
11
+ ### Patch Changes
12
+
13
+ - 76bc91c: Document Darwin hoisted-frozen install (clean tree, no win32 architectures) and require `next typegen` before `tsc` for typed-route PageProps.
14
+
3
15
  ## 1.7.11
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.11",
3
+ "version": "1.7.13",
4
4
  "description": "SE Studio agent skills for marketing site development with Contentful CMS",
5
5
  "repository": {
6
6
  "type": "git",
@@ -113,7 +113,7 @@
113
113
  "contentfulSpaceId": "bkkox68g99rn",
114
114
  "hostedMcp": "cms-edit-highlander",
115
115
  "validate": "pnpm check && pnpm type-check && pnpm validate:routes",
116
- "notes": "2026 stack is live on Vercel (develop preview, main production alias). Public DNS is still Bond/Netlify highlanderhealth.com until cutover. cms-edit DNS/OAuth for highlander.content.se.studio is a human gate."
116
+ "notes": "2026 stack is live on Vercel (develop preview, main production alias). Public DNS is still Bond/Netlify highlanderhealth.com until cutover. Hosted cms-edit: https://highlander.content.se.studio (Git production branch main)."
117
117
  }
118
118
  ]
119
119
  }
@@ -34,9 +34,12 @@ See [`validate-workflow-snippet.yml`](validate-workflow-snippet.yml). Customer m
34
34
 
35
35
  cms-edit Vercel and `check-lockfile-sync.sh` (full) run `pnpm install --frozen-lockfile --config.node-linker=hoisted`. That path requires lockfile snapshots for **linux-x64/glibc** optional binaries even when you generate the lockfile on macOS.
36
36
 
37
- Every consumer `pnpm-workspace.yaml` must include `supportedArchitectures` (current + linux, current + x64, current + glibc). Canonical copy: skill `site-workflows-deps-update` Step 3. After adding it, run `pnpm install` (not frozen) so the lockfile gains those snapshots, then verify:
37
+ Every consumer `pnpm-workspace.yaml` must include `supportedArchitectures` (current + linux, current + x64, current + glibc). Canonical copy: skill `site-workflows-deps-update` Step 3. After adding it, run `pnpm install` (not frozen) so the lockfile gains those snapshots, then verify.
38
+
39
+ **Local Darwin:** never run hoisted frozen on top of an isolated `node_modules`. That yields `ERR_PNPM_LOCKFILE_MISSING_DEPENDENCY` for `@next/swc-win32-*`. Next lists every platform SWC as optional; we do **not** add `win32` to `supportedArchitectures`. Ubuntu CI `lockfile-hoisted` is authoritative.
38
40
 
39
41
  ```bash
42
+ rm -rf node_modules
40
43
  pnpm install --frozen-lockfile --config.node-linker=hoisted
41
44
  pnpm install # restore isolated linker for local workspace packages
42
45
  ```
@@ -62,5 +65,6 @@ Apply the full stack when touching deps or CI in each repo:
62
65
  | se-website-2026 | yes | develop | yes | yes | yes |
63
66
  | pointme | yes | develop | yes | yes | yes |
64
67
  | hsd (`develop-hsd-website`; prod human-only: `production-hsd-website`) | yes | develop (+ `extended-port`) | yes | yes | yes |
68
+ | highlander-health-website-2026 | yes | develop | yes | yes | yes |
65
69
 
66
70
  Update this table as repos adopt the pattern. Every cms-edit host `pnpm-workspace.yaml` must include `supportedArchitectures` (current + linux, x64, glibc).
@@ -0,0 +1,411 @@
1
+ ---
2
+ name: coding-discipline
3
+ description: "Behavioral guidelines to reduce common LLM coding mistakes in se-core-product. Use when writing or reviewing application code, not for CMS copy or one-line fixes."
4
+ ---
5
+
6
+ # CLAUDE.md - AI Assistant Guide
7
+ Behavioral guidelines to reduce common LLM coding mistakes. Merge with project-specific instructions as needed.
8
+
9
+ **Tradeoff:** These guidelines bias toward caution over speed. For trivial tasks, use judgment.
10
+
11
+ ## 1. Think Before Coding
12
+
13
+ **Don't assume. Don't hide confusion. Surface tradeoffs.**
14
+
15
+ Before implementing:
16
+
17
+ - State your assumptions explicitly. If uncertain, ask.
18
+ - If multiple interpretations exist, present them - don't pick silently.
19
+ - If a simpler approach exists, say so. Push back when warranted.
20
+ - If something is unclear, stop. Name what's confusing. Ask.
21
+
22
+ ## 2. Simplicity First
23
+
24
+ **Minimum code that solves the problem. Nothing speculative.**
25
+
26
+ - No features beyond what was asked.
27
+ - No abstractions for single-use code.
28
+ - No "flexibility" or "configurability" that wasn't requested.
29
+ - No error handling for impossible scenarios.
30
+ - If you write 200 lines and it could be 50, rewrite it.
31
+
32
+ Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify.
33
+
34
+ ## 3. Surgical Changes
35
+
36
+ **Touch only what you must. Clean up only your own mess.**
37
+
38
+ When editing existing code:
39
+
40
+ - Don't "improve" adjacent code, comments, or formatting.
41
+ - Don't refactor things that aren't broken.
42
+ - Match existing style, even if you'd do it differently.
43
+ - If you notice unrelated dead code, mention it - don't delete it.
44
+
45
+ When your changes create orphans:
46
+
47
+ - Remove imports/variables/functions that YOUR changes made unused.
48
+ - Don't remove pre-existing dead code unless asked.
49
+
50
+ The test: Every changed line should trace directly to the user's request.
51
+
52
+ ## 4. Goal-Driven Execution
53
+
54
+ **Define success criteria. Loop until verified.**
55
+
56
+ Transform tasks into verifiable goals:
57
+
58
+ - "Add validation" → "Write tests for invalid inputs, then make them pass"
59
+ - "Fix the bug" → "Write a test that reproduces it, then make it pass"
60
+ - "Refactor X" → "Ensure tests pass before and after"
61
+
62
+ For multi-step tasks, state a brief plan:
63
+
64
+
65
+
66
+ This file provides guidance for AI assistants (Claude, Cursor, Copilot) working with this codebase.
67
+
68
+ ## Quick Start
69
+
70
+ This is a **TypeScript monorepo** for building **Next.js 16 marketing sites** with **Contentful CMS**. Customer sites are on Next 16.3; `@se-studio/*` packages still declare peer `next` `>=15.5.0 <17` for older installs.
71
+
72
+ ```bash
73
+ pnpm install # Install dependencies
74
+ pnpm build # Build all packages (required before dev)
75
+ pnpm dev # Run development mode
76
+ pnpm test # Run tests
77
+ pnpm format # Format code with Biome
78
+ ```
79
+
80
+ ## Command Reference
81
+
82
+ Use these commands from the **repository root**:
83
+
84
+ | Task | Command |
85
+ |------|---------|
86
+ | Install dependencies | `pnpm install` |
87
+ | Build all packages (required before dev) | `pnpm build` |
88
+ | Run dev (packages) | `pnpm dev` |
89
+ | Run a specific app | `pnpm --filter example-empty dev` (https://example.localhost), `pnpm --filter cms-edit-host dev` (https://cms-edit.localhost — template only; SE Studio prod: `se-website-2026/cms-edit/host`). Customer sites run from their own repos — see `docs/RELATED_PROJECTS.md`. |
90
+ | Run all apps (except ignored) | `pnpm dev:apps` or `cd apps && pnpm dev` (ignore via `SITEMAP_VALIDATE_IGNORE=true` in app’s `.env.local`) |
91
+ | Sitemap validate (prod vs portless `pnpm dev`) | Per app: `pnpm sitemap-validate` in app dir (needs `portless service install` + `pnpm dev`). Bulk: `pnpm sitemap-validate:all`. Set `SITEMAP_PROD_URL` in `.env.local`; build site-check first. |
92
+ | Smoke test (local) | Per app: `pnpm smoke-test` (`dev:dev` + HTTP on localhost port), `pnpm smoke-test:audit`, `pnpm smoke-test:cache` (`start:dev`). Uses `smoke.cases.json`; no Contentful. Regenerates: skill `se-marketing-sites-smoke-test-setup`. Set `SMOKE_TEST_IGNORE=true` to skip. |
93
+ | Smoke test (preview) | Per app: `pnpm smoke-test:preview` — curated HTTP checks against Vercel preview via `runPreviewStaticSmokeTest` (no local server). Requires `PREVIEW_SITE_URL` and `VERCEL_PROTECTION_BYPASS_TOKEN` in `.env.local`. Same `smoke.cases.json` as local smoke. |
94
+ | Run all tests | `pnpm test` |
95
+ | Test a specific package | `pnpm --filter @se-studio/core-ui test` |
96
+ | Format code | `pnpm format` |
97
+ | Type-check (packages + apps) | `pnpm type-check` |
98
+ | Lint | `pnpm lint` |
99
+ | Full validation (circular imports, skills, format, type-check) | `pnpm validate` |
100
+ | Validate skill frontmatter (Claude Code) | `pnpm skills:validate` |
101
+ | Sync skills to `.agents/skills/` | `pnpm skills:sync` |
102
+ | Worktree `.env.local` (canonical store, seed, audit, 1Password backup) | `pnpm --dir ~/source/se/se-core-product local-env seed --project <key>` — see `packages/skills/references/agent-session/local-env.md` |
103
+
104
+ ## Guides for Common App Tasks
105
+
106
+ Step-by-step guides are available as **Cursor skills**. Use them when creating or changing app-level features so you follow the right patterns and don't miss steps (e.g. registration).
107
+
108
+ | Task | Skill / doc |
109
+ |------|-------------|
110
+ | **Agent session** (core vs customer, parallel features, handoff) | `.agents/skills/site-workflows-agent-session/SKILL.md`, `docs/WORKFLOW.md` |
111
+ | **Worktree `.env.local`** | `packages/skills/references/agent-session/local-env.md`, `pnpm --dir ~/source/se/se-core-product local-env seed --project <key>` |
112
+ | Create a new **CMS component** (app) | `.agents/skills/se-marketing-sites-create-component/SKILL.md` |
113
+ | Create a new **collection** (app) | `.agents/skills/se-marketing-sites-create-collection/SKILL.md` |
114
+ | Create a new **page** or route | `.agents/skills/se-marketing-sites-create-page/SKILL.md`, `.agents/skills/se-marketing-sites-cms-routes-and-appshared/SKILL.md` |
115
+ | **Register** components/collections | `.agents/skills/se-marketing-sites-register-cms-features/SKILL.md` |
116
+ **Editor-managed redirects** (rebuild pattern + migrations) | `.agents/skills/se-marketing-sites-redirects/SKILL.md` |
117
+ | **Media** (images, videos, animations) | `.agents/skills/se-marketing-sites-handling-media/SKILL.md` |
118
+ | **Styling** (typography, colours, grids) | `.agents/skills/se-marketing-sites-styling-system/SKILL.md` |
119
+ | **Lib/CMS structure** (cms.ts, registrations) | `.agents/skills/se-marketing-sites-lib-cms-structure/SKILL.md` |
120
+ | **Sync Contentful schema** to core (golden diff, migration runbook) | `.agents/skills/contentful-cms-sync-schema/SKILL.md`, `docs/schema-audit/` |
121
+ | **Edit CMS content** (pages, components, articles) | `.agents/skills/contentful-cms-core/SKILL.md` |
122
+ | **CMS guidelines — orchestration** (full **fresh** clean regen vs **sync** incremental + stale removal vs **merge-only**) | `.agents/skills/contentful-cms-update-cms-guidelines/SKILL.md` — if the user is vague (“regenerate guidelines”), confirm **fresh** vs **sync** before acting |
123
+ | **CMS guidelines — fragments** (full / single / merge-only; prefer **update-cms-guidelines** for true total regeneration) | `.agents/skills/contentful-cms-generate-cms-guidelines/SKILL.md` |
124
+
125
+ **Skills — canonical source and sync:** All SE Studio skills live in **`packages/skills/skills/`** (the `@se-studio/skills` npm package). **In the monorepo**, edit sources there, run **`pnpm skills:validate`**, then **`pnpm skills:sync`** to copy into **`.agents/skills`**. The repo root keeps **`.cursor/skills`** as a **symlink** to **`.agents/skills`**. **External projects** install skills via the `skills` CLI: `npx skills add @se-studio/skills`. Do not edit skills under **`.agents/skills`** by hand. Frontmatter rules: [`packages/skills/README.md`](packages/skills/README.md).
126
+
127
+ See also **docs/AI_QUICK_REFERENCE.md** for a short task → doc/skill index.
128
+
129
+ ## Package Dependency Graph
130
+
131
+ ```
132
+ ┌──────────────────────────────────────────────────────────────────────────────┐
133
+ │ APPS │
134
+ │ ┌─────────────────┐ ┌─────────────────┐ (+ customer sites in separate repos) │
135
+ │ │ example-empty │ │ cms-edit-host │ see docs/RELATED_PROJECTS.md │
136
+ │ │ example.localhost│ │ cms-edit.localhost│ │
137
+ │ └────────┬────────┘ └────────┬────────┘ │
138
+ │ └────────────────────┘ │
139
+ │ ▼ │
140
+ ├─────────────────────────────────────────────────────────────────┤
141
+ │ PACKAGES │
142
+ │ │
143
+ │ ┌──────────────────────────────────────────────────────────┐ │
144
+ │ │ core-ui │ │
145
+ │ │ React components, CMS rendering, analytics │ │
146
+ │ └─────────────────────────┬────────────────────────────────┘ │
147
+ │ │ │
148
+ │ ┌───────────────────┼────────────────────┐ │
149
+ │ ▼ ▼ ▼ │
150
+ │ ┌─────────────────┐ ┌─────────────────────┐ ┌──────────────┐ ┌────────────────┐ │
151
+ │ │ contentful- │ │ project-build │ │ ab-testing │ │ skills │ │
152
+ │ │ rest-api │ │ Build tools, │ │ A/B testing │ │ Agent skills │ │
153
+ │ │ CDA/CPA client │ │ Tailwind, CLI │ │ framework │ │ (@se-studio/ │ │
154
+ │ └────────┬────────┘ └─────────────────────┘ └──────┬───────┘ │ skills) │ │
155
+ │ │ │ └────────────────┘ │
156
+ │ │ │ │
157
+ │ │ │ │
158
+ │ ▼ │ │
159
+ │ ┌───────────────────────────────────────────────────────────▼─────┐ │
160
+ │ │ core-data-types │ │
161
+ │ │ TypeScript types, interfaces, type guards │ │
162
+ │ │ (No runtime dependencies - pure types) │ │
163
+ │ └─────────────────────────────────────────────────────────┘ │
164
+ │ │
165
+ │ ┌─────────────────────────────────────────────────────────┐ │
166
+ │ │ markdown-renderer │ │
167
+ │ │ Utilities for converting Contentful to Markdown │ │
168
+ │ │ (Depends on contentful-rest-api, core-data-types) │ │
169
+ │ └─────────────────────────────────────────────────────────┘ │
170
+ │ │
171
+ │ ┌─────────────────────────────────────────────────────────┐ │
172
+ │ │ search │ │
173
+ │ │ AI-powered site search with Upstash Search │ │
174
+ │ │ (Depends on contentful-rest-api, core-data-types, │ │
175
+ │ │ markdown-renderer, @upstash/search) │ │
176
+ │ └─────────────────────────────────────────────────────────┘ │
177
+ └─────────────────────────────────────────────────────────────────┘
178
+ ```
179
+
180
+ ## Key Files to Understand
181
+
182
+ | File | Purpose |
183
+ |------|---------|
184
+ | `packages/core-data-types/src/index.ts` | All shared type exports |
185
+ | `packages/contentful-rest-api/src/api.ts` | Contentful API functions |
186
+ | `packages/contentful-rest-api/src/converters/` | Entry-to-model converters |
187
+ | `packages/core-ui/src/components/CmsContent.tsx` | Main CMS renderer |
188
+ | `packages/core-ui/CMS_INFRASTRUCTURE.md` | CMS system documentation |
189
+ | `packages/ab-testing/src/middleware/index.ts` | A/B testing middleware handler |
190
+ | `packages/search/src/types.ts` | Search types and configuration |
191
+ | `packages/search/src/indexing/rebuild.ts` | Full search index rebuild |
192
+ | `packages/search/src/webhook/handler.ts` | Webhook-driven search index updates |
193
+ | `packages/markdown-renderer/src/MarkdownConverter.ts` | Contentful to Markdown logic |
194
+ | `turbo.json` | Build pipeline configuration |
195
+ | `biome.json` | Code style rules |
196
+
197
+ ## Common Tasks
198
+
199
+ ### Adding a New Content Type
200
+
201
+ 1. **Define types** in `core-data-types/src/types/`
202
+ 2. **Export types** from `core-data-types/src/index.ts`
203
+ 3. **Create converter** in `contentful-rest-api/src/converters/`
204
+ 4. **Add API function** in `contentful-rest-api/src/api.ts`
205
+ 5. **Create renderer** in the app's components
206
+
207
+ ### Adding a New UI Component (in core-ui package)
208
+
209
+ For **shared package** components (used across apps):
210
+
211
+ 1. Create component in `packages/core-ui/src/components/`
212
+ 2. Export from `packages/core-ui/src/index.ts`
213
+ 3. Add tests in `packages/core-ui/src/__tests__/`
214
+ 4. Document props with JSDoc
215
+
216
+ ### Adding a New CMS Component (in an app)
217
+
218
+ For **app-level** components that render CMS content (Hero, CTA, etc.):
219
+
220
+ 1. Use the **create-component** skill: `.agents/skills/se-marketing-sites-create-component/SKILL.md`
221
+ 2. Follow the four-layer pattern (Core, Wrapper, Renderer, Registration) and the template there
222
+ 3. **Register** the component in the app's `src/lib/registrations.ts` (add to `componentRegistrationsList`). The **register-cms-features** skill describes this; missing registrations cause a type error in `cms.ts` via `buildComponentRecord`.
223
+ 4. Ensure the `name` in `defineComponent` matches the CMS `componentType` exactly (name is defined once in the registration).
224
+
225
+ ### Heading hierarchy
226
+
227
+ Use `Element` from `getSizingInformation(index)` for the main heading of each component/collection; use `ChildElement` for headings of items inside a collection. Render **preHeading** and **postHeading** as `<p>` with a typography class, never as heading tags. See `.cursorrules` (Heading and pre/post rules) and the create-component skill.
228
+
229
+ ### Fetching Contentful Data
230
+
231
+ ```typescript
232
+ import { contentfulPageRest } from '@se-studio/contentful-rest-api';
233
+
234
+ const page = await contentfulPageRest(
235
+ {
236
+ spaceId: process.env.CONTENTFUL_SPACE_ID!,
237
+ accessToken: process.env.CONTENTFUL_ACCESS_TOKEN!,
238
+ environment: 'master',
239
+ },
240
+ 'home', // slug
241
+ {
242
+ preview: false,
243
+ cache: { tags: ['page#home'], revalidate: 3600 }
244
+ }
245
+ );
246
+ ```
247
+
248
+ ### Rendering CMS Content
249
+
250
+ ```tsx
251
+ import { CmsContent } from '@se-studio/core-ui';
252
+
253
+ <CmsContent
254
+ content={page}
255
+ config={rendererConfig}
256
+ context={{ pageLink: { slug: page.slug, title: page.title } }}
257
+ />
258
+ ```
259
+
260
+ ## TypeScript Patterns
261
+
262
+ ### Type Guards (Runtime Type Checking)
263
+ ```typescript
264
+ import { isPage, isComponent, isImage } from '@se-studio/core-data-types';
265
+
266
+ if (isPage(content)) {
267
+ console.log(content.slug); // TypeScript knows content is IBasePage
268
+ }
269
+ ```
270
+
271
+ ### Strict Index Access
272
+ The project uses `noUncheckedIndexedAccess`, so array/object index access returns `T | undefined`:
273
+ ```typescript
274
+ const items = ['a', 'b', 'c'];
275
+ const first = items[0]; // string | undefined - must handle undefined!
276
+ if (first) {
277
+ console.log(first.toUpperCase()); // Now safe
278
+ }
279
+ ```
280
+
281
+ ### Component Props Pattern
282
+ ```typescript
283
+ // Define explicit prop types for presentational components
284
+ export interface HeroProps {
285
+ heading: string | null;
286
+ body: unknown;
287
+ visual: IResponsiveVisual | undefined;
288
+ }
289
+
290
+ // Extract props in the renderer
291
+ export const HeroRenderer: ComponentRenderer<ProjectConfig> = ({ information }) => {
292
+ return <HeroCore
293
+ heading={information.heading}
294
+ body={information.body}
295
+ visual={information.visual}
296
+ />;
297
+ };
298
+ ```
299
+
300
+ ## Code Style Requirements
301
+
302
+ - **Styling**: Tailwind only. Do not use CSS modules (`*.module.css`). Use Tailwind classes or `src/app/globals.css` for shared styles.
303
+ - **Biome** for linting/formatting (not ESLint/Prettier)
304
+ - Single quotes, semicolons, trailing commas
305
+ - `import type` for type-only imports
306
+ - `node:` protocol for Node.js built-ins
307
+ - 100 character line width
308
+
309
+ Run `pnpm format` before committing.
310
+
311
+ ## Testing
312
+
313
+ ```bash
314
+ pnpm test # Run all tests
315
+ pnpm --filter @se-studio/core-ui test # Test specific package
316
+ ```
317
+
318
+ Tests use **Vitest** and live in `__tests__/` directories.
319
+
320
+ ## Environment Setup
321
+
322
+ **Worktrees:** `.env.local` is gitignored and will be missing after `git worktree add`. Seed from `~/source/local-env` with `pnpm --dir ~/source/se/se-core-product local-env seed --project <key>`. Do not invent a stub file or symlink at develop. Details: `packages/skills/references/agent-session/local-env.md`.
323
+
324
+ Apps need these environment variables in `.env.local`:
325
+
326
+ ```bash
327
+ CONTENTFUL_SPACE_ID=your-space-id
328
+ CONTENTFUL_ACCESS_TOKEN=your-delivery-token
329
+ CONTENTFUL_PREVIEW_ACCESS_TOKEN=your-preview-token
330
+ CONTENTFUL_ENVIRONMENT=master
331
+ ```
332
+
333
+ ### Optional: Verbose logging
334
+
335
+ Uncomment in `.env.local` (or `.env.example`) to enable detailed console output from specific subsystems (silent by default):
336
+
337
+ ```bash
338
+ # LOG_CMS=1 # Contentful fetching, resolution, revalidation, unknown component/collection types, unknown colour/text-style names
339
+ # LOG_SVG_SPRITE=1 # SVG icon processing and sprite generation warnings
340
+ ```
341
+
342
+ ## Server vs Client: cms-server
343
+
344
+ - **Do not import `cms-server` (or `@/lib/cms-server`) in files that have `'use client'`.** That module is server-only (Contentful config). Client components must not import it; pass server-rendered content as `children` from server components instead.
345
+ - **Do not import preview/fetch helpers from `cms-server` in components or collections.** That causes circular dependencies (registrations → components → cms-server → registrations). Use `getPreviewFieldProps(rendererConfig, id, fieldId)` and `getPreviewResponsiveVisualFieldProps(rendererConfig, id, 'visual', 'mobileVisual')` from `@se-studio/core-ui`, and `rendererConfig?.fetchHelpers` for data. Pass `previewHelpers` to `<Section>` and `rendererConfig` to `<SectionLinks>`.
346
+ - Each app's `cms-server.ts` has `import 'server-only'`. If a client component imports it, the build will fail with a clear "cannot be imported from a Client Component" error. See `docs/SERVER_CLIENT_BOUNDARIES.md`.
347
+
348
+ ## Troubleshooting
349
+
350
+ | Problem | Solution |
351
+ |---------|----------|
352
+ | "Cannot find module '@se-studio/...'" | Run `pnpm build` from root |
353
+ | "Cannot find name 'PageProps'" in example-empty | `typedRoutes` defines `PageProps` in `.next/types/routes.d.ts`. `pnpm --filter example-empty type-check` runs `next typegen` first. Delete a stale `apps/example-empty/.tsbuildinfo` if tsc still misses it. |
354
+ | Port already in use / `.localhost` not on 443 | Install `portless service install`. `pnpm dev` uses named URLs. Smoke still uses localhost:3014 via `dev:dev`. Customer sites: `docs/RELATED_PROJECTS.md` |
355
+ | Contentful 401 error | Check access token and space ID |
356
+ | "This module cannot be imported from a Client Component" | You imported `cms-server` (or a file that uses it) in a `'use client'` file. Move content rendering to a server component and pass it as `children`. |
357
+
358
+ ## Keeping Documentation Updated
359
+
360
+ When making changes, update the relevant documentation:
361
+
362
+ | Change | Update |
363
+ |--------|--------|
364
+ | New content type | `specs/CONTENT_MODEL.md` |
365
+ | New component pattern | `specs/COMPONENT_PATTERNS.md` |
366
+ | New API function | `packages/contentful-rest-api/README.md` and `packages/contentful-rest-api/docs/llms.md` |
367
+ | New package | `README.md`, `CLAUDE.md`, `docs/ARCHITECTURE.md` |
368
+ | New app | `README.md`, `CLAUDE.md`, `docs/DEVELOPMENT.md`, `docs/ARCHITECTURE.md`, port list |
369
+ | New env variable | All `.env.example` files |
370
+ | Workflow change | `docs/DEVELOPMENT.md`, `docs/WORKFLOW.md` |
371
+ | Worktree / local env handling | `packages/skills/references/agent-session/local-env.md` |
372
+
373
+ **Documentation locations:**
374
+ - `docs/` - Architecture and development guides
375
+ - `specs/` - Content model and component specifications
376
+ - `packages/*/README.md` - Package-specific docs (human-facing)
377
+ - `packages/*/docs/llms.md` - LLM-optimised quick-reference per package (also published to npm)
378
+ - `.cursorrules` - AI conventions (update if patterns change)
379
+
380
+ ## Links
381
+
382
+ - [Related Projects](./docs/RELATED_PROJECTS.md) – Client and studio projects that consume these packages (Contentful space IDs, environments, repo paths)
383
+ - [AI Quick Reference](./docs/AI_QUICK_REFERENCE.md) – Task → doc/skill index for common app tasks
384
+ - [GitHub issues implementation status](./docs/GITHUB_ISSUES_IMPLEMENTATION_STATUS.md) – closed issues mapped to code; open backlog summary
385
+ - [Content Structure Guide](./docs/CONTENT_STRUCTURE_GUIDE.md) – Content author guide for CMS workflows
386
+ - [Server vs Client Boundaries](./docs/SERVER_CLIENT_BOUNDARIES.md) – cms-server rule and pattern
387
+ - [core-ui package export boundaries](./packages/core-ui/docs/PACKAGE_EXPORT_BOUNDARIES.md) – main vs `/server` entry; prevent client bundle CMS leaks
388
+ - [Contentful webhook revalidation](./docs/CONTENTFUL_WEBHOOK_REVALIDATION.md) – Contentful webhooks for cache revalidation
389
+ - [CMS Infrastructure Guide](./packages/core-ui/CMS_INFRASTRUCTURE.md)
390
+ - [Contentful REST API Docs](./packages/contentful-rest-api/README.md) — LLM ref: [docs/llms.md](./packages/contentful-rest-api/docs/llms.md)
391
+ - [Core Data Types Docs](./packages/core-data-types/README.md) — LLM ref: [docs/llms.md](./packages/core-data-types/docs/llms.md)
392
+ - [Core UI Docs](./packages/core-ui/README.md) — LLM ref: [docs/llms.md](./packages/core-ui/docs/llms.md)
393
+ - [A/B Testing Docs](./packages/ab-testing/README.md) — LLM ref: [docs/llms.md](./packages/ab-testing/docs/llms.md)
394
+ - [HubSpot Docs](./packages/hubspot/README.md) — LLM ref: [docs/llms.md](./packages/hubspot/docs/llms.md)
395
+ - [Search Docs](./packages/search/README.md) — LLM ref: [docs/llms.md](./packages/search/docs/llms.md)
396
+ - [Markdown Renderer Docs](./packages/markdown-renderer/README.md) — LLM ref: [docs/llms.md](./packages/markdown-renderer/docs/llms.md)
397
+ - [Contentful CMS CLI Docs](./packages/contentful-cms/README.md)
398
+
399
+ ### For consuming projects (in node_modules)
400
+
401
+ When working in a project that installs `@se-studio` packages, tell LLMs to read the relevant doc in `node_modules/`:
402
+
403
+ - `node_modules/@se-studio/contentful-rest-api/docs/llms.md`
404
+ - `node_modules/@se-studio/core-data-types/docs/llms.md`
405
+ - `node_modules/@se-studio/core-ui/docs/llms.md`
406
+ - `node_modules/@se-studio/ab-testing/docs/llms.md`
407
+ - `node_modules/@se-studio/hubspot/docs/llms.md`
408
+ - `node_modules/@se-studio/search/docs/llms.md`
409
+ - `node_modules/@se-studio/markdown-renderer/docs/llms.md`
410
+
411
+ These are the source of truth — training data is outdated. See the example app `AGENTS.md` files for the ready-to-copy block.
@@ -31,7 +31,8 @@ Use this skill when you need to read or edit content in Contentful using **hoste
31
31
  All `save` operations create **draft** versions. A human must review and publish in Contentful.
32
32
 
33
33
  **Assets:** Upload **is** supported (`asset upload`). Default workflow: **search and reuse** existing assets first (`index sync` → `asset search`). When uploading:
34
- - **Hosted MCP:** always `cms_edit_request_staged_upload` → curl → `asset upload --staged` (never `--base64`)
34
+ - **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
+ - **SVG/PDF/Lottie:** `cms_edit_request_staged_upload` → curl → `asset upload --staged` (never `--base64`)
35
36
  - Use a **sensible fileName** and **descriptive title** (and alt text where the site uses it)
36
37
  - Avoid oversized images — width over **2000px** is usually wasteful for web (exact limits vary by project; check `asset audit` / media review guidance)
37
38
  - Prefer `--if-exists-by-filename` to avoid duplicates
@@ -371,13 +372,8 @@ cms-edit asset search "hero background"
371
372
  cms-edit asset search --filename istockphoto-123.jpg
372
373
  cms-edit asset search --filename-match 'istockphoto-.*'
373
374
 
374
- # Local CLI — URL or base64 (hosted MCP rejects --base64)
375
- cms-edit asset upload --url https://example.com/image.jpg --if-exists-by-filename
376
- cms-edit asset upload --base64 "$B64" --mime image/png --file-name poster.png
377
-
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"]
375
+ # Raster/video: cms_edit_media prepare → wait → catalog → import (video: import only).
376
+ # SVG/PDF/Lottie: cms_edit_request_staged_upload → curl → asset upload --staged
381
377
 
382
378
  # Upload and create a Media wrapper in one step (--media-name defaults to asset title)
383
379
  cms-edit asset upload ./figure.png --with-media --media-position Middle
@@ -36,6 +36,16 @@ export default function CmsRoutesLayout({ children }: { children: React.ReactNod
36
36
 
37
37
  Base paths come from `@/lib/constants` (e.g. ARTICLES_BASE = `/learning-hub` or `/articles`).
38
38
 
39
+ ## Type-check (typed routes)
40
+
41
+ Next 16 puts `PageProps` in `.next/types`. A cold worktree has no `.next`, so bare `tsc --noEmit` fails on CMS `page.tsx`. Marketing apps must use:
42
+
43
+ ```json
44
+ "type-check": "next typegen && tsc --noEmit --incremental false"
45
+ ```
46
+
47
+ Keep committed `next-env.d.ts` importing `./.next/types/routes.d.ts` and `./.next/types/root-params.d.ts` — not `.next/dev/types` (that path is from `next dev`). Do not commit Next rewriting those imports to double quotes if Biome uses single quotes.
48
+
39
49
  ## appShared Modules
40
50
 
41
51
  Route files are thin wrappers. Logic lives in `src/appShared/`:
@@ -208,12 +208,16 @@ rg '"node"' package.json apps/*/package.json packages/*/package.json 2>/dev/null
208
208
 
209
209
  ## Step 6 — Validate (unified for all repos)
210
210
 
211
- If the registry project has `cms-edit/host` in `pnpm-workspace.yaml`, run the frozen hoisted install check first:
211
+ If the registry project has `cms-edit/host` in `pnpm-workspace.yaml`, run the frozen hoisted install check first. **Do not** mix an isolated-linker `node_modules` with hoisted frozen — on Darwin that fails with `ERR_PNPM_LOCKFILE_MISSING_DEPENDENCY` for `@next/swc-win32-*` (Next lists every platform SWC as optional; `supportedArchitectures` does not include win32). Ubuntu CI `lockfile-hoisted` is the source of truth. Locally:
212
212
 
213
213
  ```bash
214
+ rm -rf node_modules
214
215
  pnpm install --frozen-lockfile --config.node-linker=hoisted
216
+ pnpm install # restore isolated linker for day-to-day work
215
217
  ```
216
218
 
219
+ Do **not** add `win32` to `supportedArchitectures` to make Mac hoisted pass.
220
+
217
221
  Always run the patches check **once**, then the project validate from the registry:
218
222
 
219
223
  ```bash
@@ -284,6 +288,7 @@ See [`references/lockfile-sync/README.md`](../../references/lockfile-sync/README
284
288
  | Issue | Action |
285
289
  |-------|--------|
286
290
  | `ERR_PNPM_OUTDATED_LOCKFILE` on frozen/hoisted install | `package.json` and `pnpm-workspace.yaml` overrides out of sync with lockfile — re-run `pnpm update` for the package and align `overrides` |
291
+ | `ERR_PNPM_LOCKFILE_MISSING_DEPENDENCY` (`@next/swc-win32-*`) on Darwin hoisted frozen | Isolated `node_modules` mixed with hoisted linker — `rm -rf node_modules`, hoisted frozen, then `pnpm install`. Do not add win32 to `supportedArchitectures`. Trust Ubuntu `lockfile-hoisted` |
287
292
  | `ERR_PNPM_LOCKFILE_MISSING_DEPENDENCY` (`rollup-linux-*`, Sharp, etc.) on hoisted frozen install | Missing `supportedArchitectures` (current + linux, x64, glibc) — add the Step 3 block, run `pnpm install`, then re-verify hoisted |
288
293
  | `next` or `@types/node` still outdated to wrong major | Re-run overrides + safety re-pin; check `pnpm-workspace.yaml` overrides |
289
294
  | Non-`@se-studio` package still outdated after update | Likely within 24h of npm publish — wait and re-run; **do not** bypass `minimumReleaseAge` |