@se-studio/project-build 1.0.131 → 1.0.133

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.
Files changed (42) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +13 -14
  3. package/package.json +2 -4
  4. package/dist/management/sync-skills.d.ts +0 -4
  5. package/dist/management/sync-skills.d.ts.map +0 -1
  6. package/dist/management/sync-skills.js +0 -97
  7. package/dist/management/sync-skills.js.map +0 -1
  8. package/dist/seskills.d.ts +0 -9
  9. package/dist/seskills.d.ts.map +0 -1
  10. package/dist/seskills.js +0 -32
  11. package/dist/seskills.js.map +0 -1
  12. package/skills/contentful-cms/alt-text-audit/SKILL.md +0 -60
  13. package/skills/contentful-cms/cms-guidelines/README.md +0 -166
  14. package/skills/contentful-cms/cms-guidelines/colour-hint-prompt.md +0 -77
  15. package/skills/contentful-cms/cms-guidelines/evaluation-prompt.md +0 -84
  16. package/skills/contentful-cms/cms-guidelines/generate-component-guidelines.md +0 -126
  17. package/skills/contentful-cms/cms-guidelines/generation-prompt.md +0 -231
  18. package/skills/contentful-cms/cms-guidelines/html-component-authoring.md +0 -401
  19. package/skills/contentful-cms/cms-guidelines/validation-prompt.md +0 -170
  20. package/skills/contentful-cms/cms-guidelines/variant-loop.md +0 -189
  21. package/skills/contentful-cms/cms-guidelines/variant-proposal-prompt.md +0 -131
  22. package/skills/contentful-cms/core/SKILL.md +0 -793
  23. package/skills/contentful-cms/generate-all-guidelines/SKILL.md +0 -313
  24. package/skills/contentful-cms/generate-cms-guidelines/SKILL.md +0 -313
  25. package/skills/contentful-cms/image-guide/SKILL.md +0 -240
  26. package/skills/contentful-cms/manifest.json +0 -11
  27. package/skills/contentful-cms/navigation/SKILL.md +0 -23
  28. package/skills/contentful-cms/rich-text/SKILL.md +0 -96
  29. package/skills/contentful-cms/schema-org/SKILL.md +0 -74
  30. package/skills/contentful-cms/screenshots/SKILL.md +0 -46
  31. package/skills/contentful-cms/seo-descriptions/SKILL.md +0 -54
  32. package/skills/contentful-cms/templates/SKILL.md +0 -21
  33. package/skills/contentful-cms/update-cms-guidelines/SKILL.md +0 -348
  34. package/skills/se-marketing-sites/cms-routes-and-appshared/SKILL.md +0 -99
  35. package/skills/se-marketing-sites/create-collection/SKILL.md +0 -295
  36. package/skills/se-marketing-sites/create-component/SKILL.md +0 -250
  37. package/skills/se-marketing-sites/create-page/SKILL.md +0 -129
  38. package/skills/se-marketing-sites/curate-showcase-mocks/SKILL.md +0 -343
  39. package/skills/se-marketing-sites/handling-media/SKILL.md +0 -195
  40. package/skills/se-marketing-sites/lib-cms-structure/SKILL.md +0 -83
  41. package/skills/se-marketing-sites/register-cms-features/SKILL.md +0 -95
  42. package/skills/se-marketing-sites/styling-system/SKILL.md +0 -122
@@ -1,343 +0,0 @@
1
- ---
2
- name: curate-showcase-mocks
3
- description: Extracts real component/collection data from Contentful and curates the best examples into showcase-mocks.json, making the CMS showcase display realistic content instead of generic placeholder text.
4
- license: Private
5
- metadata:
6
- author: se-core-product
7
- version: "2.1.0"
8
- ---
9
-
10
- # Curate Showcase Mocks
11
-
12
- This skill refreshes the CMS showcase with realistic content from the live Contentful space.
13
- It uses a **two-phase CLI pipeline** — extraction followed by LLM-driven curation — to produce
14
- `src/generated/showcase-mocks.json`, which the showcase loads at runtime.
15
-
16
- It is **Step 2** of **`update-cms-guidelines`** mode **`fresh`** (after the clean slate). Realistic mocks and `accepted-variants` files are **required** before bulk screenshot capture in **generate-all-guidelines**.
17
-
18
- ## When to use
19
-
20
- Run this skill when:
21
- - A new app has been populated in Contentful and the showcase still shows placeholder text
22
- - The CMS content has been significantly updated and the showcase looks stale
23
- - New component or collection types have been added and need good mock data
24
- - You are doing a **full CMS guidelines regeneration** and need fresh showcase data before Phase 1 / 1b screenshots
25
-
26
- ## Prerequisites
27
-
28
- - The app's `.env.local` must contain `CONTENTFUL_SPACE_ID`, `CONTENTFUL_ACCESS_TOKEN`, and `CONTENTFUL_ENVIRONMENT_NAME`
29
- - An LLM API key in `.env.local`: `OPENAI_API_KEY` (preferred) or `ANTHROPIC_API_KEY`
30
- - Optional: `CONTENTFUL_PREVIEW_ACCESS_TOKEN` to also include draft/unpublished entries
31
- - For monorepo apps: all packages must be built (`pnpm build` from repo root)
32
- - The app must be fully set up (see **First-time setup** below if not yet done)
33
-
34
- ## First-time setup (new apps)
35
-
36
- Before running this skill on a new app, four one-time changes are required.
37
-
38
- ### 1 — Add scripts to `package.json`
39
-
40
- **Monorepo app** (uses local packages via relative paths):
41
-
42
- ```json
43
- "generate-showcase": "node ../../packages/project-build/dist/generate-showcase-data.js",
44
- "generate-showcase-mocks": "node ../../packages/project-build/dist/generate-showcase-mocks.js"
45
- ```
46
-
47
- **External/standalone project** (uses npm-installed packages):
48
-
49
- ```json
50
- "generate-showcase": "node node_modules/@se-studio/project-build/dist/generate-showcase-data.js",
51
- "generate-showcase-mocks": "node node_modules/@se-studio/project-build/dist/generate-showcase-mocks.js"
52
- ```
53
-
54
- Alternatively for external projects, use the installed binaries directly (available on PATH after install):
55
-
56
- ```bash
57
- generate-showcase-data # runs in-place from the project root
58
- generate-showcase-mocks
59
- ```
60
-
61
- ### 2 — Gitignore the generated files
62
-
63
- In the app's `.gitignore`, add:
64
-
65
- ```
66
- # Generated showcase files (large, regenerable — curated mocks committed separately)
67
- src/generated/showcase-examples.json
68
- src/generated/showcase-mocks-draft.json
69
- src/generated/cms-discovery/accepted-variants/
70
- ```
71
-
72
- ### 3 — Wire the render pages to use curated mocks
73
-
74
- Both `src/app/(cms-dev)/cms/showcase/render/page.tsx` and `render-all/page.tsx` need to import
75
- `mergeShowcaseMocks` and the curated mocks file.
76
-
77
- **`render/page.tsx`** — change from:
78
-
79
- ```tsx
80
- import { DEFAULT_SHOWCASE_CONTROL_STATE, ShowcaseRenderPage } from '@se-studio/core-ui';
81
- // ... other imports ...
82
-
83
- export default async function Page(...) {
84
- return (
85
- <ShowcaseRenderPage
86
- componentMockMap={componentMockMap}
87
- collectionMockMap={collectionMockMap}
88
- collectionCardMockMap={collectionCardMockMap}
89
- ...
90
- />
91
- );
92
- }
93
- ```
94
-
95
- to:
96
-
97
- ```tsx
98
- import { DEFAULT_SHOWCASE_CONTROL_STATE, ShowcaseRenderPage, mergeShowcaseMocks } from '@se-studio/core-ui';
99
- // ... other imports ...
100
- import curatedMocks from '@/generated/showcase-mocks.json';
101
-
102
- const { componentMockMap: mergedComponentMocks, collectionMockMap: mergedCollectionMocks, collectionCardMockMap: mergedCardMocks } =
103
- mergeShowcaseMocks(curatedMocks, { componentMockMap, collectionMockMap, collectionCardMockMap });
104
-
105
- export default async function Page(...) {
106
- return (
107
- <ShowcaseRenderPage
108
- componentMockMap={mergedComponentMocks}
109
- collectionMockMap={mergedCollectionMocks}
110
- collectionCardMockMap={mergedCardMocks}
111
- ...
112
- />
113
- );
114
- }
115
- ```
116
-
117
- Apply the same pattern to **`render-all/page.tsx`**.
118
-
119
- ### 4 — Create an empty `showcase-mocks.json` stub
120
-
121
- Create `src/generated/showcase-mocks.json` so the import compiles before curated data exists:
122
-
123
- ```json
124
- {
125
- "curatedAt": "2026-01-01T00:00:00.000Z",
126
- "components": {},
127
- "collections": {}
128
- }
129
- ```
130
-
131
- Once these four steps are done, proceed with the steps below.
132
-
133
- ---
134
-
135
- ## Pipeline Overview
136
-
137
- The workflow is now a **three-step pipeline**:
138
-
139
- ```
140
- Step 1: generate-showcase-data → showcase-examples.json (all CMS data, sorted by completeness)
141
- Step 2: generate-showcase-mocks → showcase-mocks-draft.json (LLM selects best + proposes variants)
142
- Step 3: AI review (this skill) → showcase-mocks.json (final curated mocks, committed)
143
- ```
144
-
145
- Steps 1 and 2 are automated CLI commands. Step 3 is where you (the AI) review the draft,
146
- adjust anything the LLM got wrong, handle layout variants, and write the final committed file.
147
-
148
- ---
149
-
150
- ## Steps
151
-
152
- ### Step 1 — Run the extraction script
153
-
154
- Run the CLI to fetch all component/collection entries from Contentful:
155
-
156
- **Monorepo:**
157
- ```bash
158
- pnpm --filter {appName} generate-showcase
159
- ```
160
-
161
- **External project (from project root):**
162
- ```bash
163
- node node_modules/@se-studio/project-build/dist/generate-showcase-data.js
164
- ```
165
-
166
- **Optional flags:**
167
- - `--include-drafts` — also fetches draft/unpublished entries via the Preview API (requires `CONTENTFUL_PREVIEW_ACCESS_TOKEN`)
168
- - `--all-types` — fetches all entry content types without a filter (instead of fetching component and collection separately)
169
-
170
- This writes `src/generated/showcase-examples.json` — every example grouped by type, sorted by
171
- `fieldCompleteness` descending. This file is gitignored.
172
-
173
- ### Step 2 — Run the LLM curation script
174
-
175
- **Monorepo:**
176
- ```bash
177
- pnpm --filter {appName} generate-showcase-mocks
178
- ```
179
-
180
- **External project:**
181
- ```bash
182
- node node_modules/@se-studio/project-build/dist/generate-showcase-mocks.js
183
- ```
184
-
185
- This reads `showcase-examples.json`, calls the LLM (OpenAI or Anthropic — auto-detected from
186
- `.env.local`), and produces:
187
- - `src/generated/showcase-mocks-draft.json` — best mock per type + proposed variant param sets
188
- - `src/generated/cms-discovery/accepted-variants/{components|collections|externals}/<slug>.json` — per-type variant files (in mode subdir)
189
-
190
- **Optional flags:**
191
- - `--model <model>` — override the LLM model (e.g. `--model gpt-4o`)
192
- - `--types <Type1,Type2>` — limit to specific type names (comma-separated, useful for re-running single types)
193
-
194
- ### Step 3 — Read the draft and registrations
195
-
196
- Read these files:
197
-
198
- 1. `src/generated/showcase-mocks-draft.json` — the LLM's selected mocks + variant proposals
199
- 2. `src/lib/registrations.ts` — the app's component/collection registrations
200
-
201
- From the registrations file, collect:
202
- - The full list of registered component type names
203
- - The full list of registered collection type names
204
- - Any registrations with `showcaseExclude: true` — these types must be skipped entirely
205
-
206
- Check the draft against the registrations: are there registered types missing from the draft?
207
- If so, check `showcase-examples.json` directly to find examples for those types.
208
-
209
- ### Step 4 — Review and refine mocks
210
-
211
- For each type in the draft:
212
-
213
- **Validate the LLM selection:**
214
- - Confirm the selected mock has a real heading (not a test entry)
215
- - Confirm it has a working visual URL (if the field exists)
216
- - Confirm the mock fields are complete and reflect real brand content
217
-
218
- **Add layout variants not in the CMS:**
219
- Some types have meaningful variants that may not exist as separate CMS entries — a flipped
220
- layout, a narrow/wide version, or a no-visual state. These can be represented by adjusting
221
- the base mock with URL param overrides. Review each type's variant proposals from the LLM
222
- (in `showcase-mocks-draft.json`) and add any important ones that are missing:
223
-
224
- - For a Hero with a left-layout variant: add a variant with `{ "showcaseParams": { "flip": "true" } }` or similar
225
- - For a content block with a narrow option: `{ "showcaseParams": { "width": "narrow" } }`
226
- - Adjust the LLM's proposed params to match the actual param names used in the component's showcase controls
227
-
228
- **For collections — curating cards:**
229
- - Select ALL cards from the best example (do not cap — use the real count)
230
- - If fewer than 4 cards, check the next-best example for additional cards
231
- - Cards with no heading and no body are useless — skip them
232
-
233
- ### Step 5 — Write showcase-mocks.json
234
-
235
- Write the curated data to `src/generated/showcase-mocks.json`. This file IS committed to git.
236
-
237
- Use the LLM draft as the starting point and apply your corrections from Step 4.
238
-
239
- **Format:**
240
-
241
- ```json
242
- {
243
- "curatedAt": "2026-02-28T14:00:00.000Z",
244
- "components": {
245
- "Hero": {
246
- "heading": "Mental health care for kids and teens. Parenting support for you.",
247
- "preHeading": "Brightline",
248
- "body": { "json": { "nodeType": "document", "content": [...] } },
249
- "visual": { "width": 1200, "height": 800, "url": "https://images.ctfassets.net/..." },
250
- "backgroundColour": "Off White"
251
- }
252
- },
253
- "collections": {
254
- "FAQ": {
255
- "mock": { "heading": "Top FAQs" },
256
- "cards": [
257
- { "heading": "Who is Brightline?", "body": { "json": { ... } } }
258
- ]
259
- }
260
- }
261
- }
262
- ```
263
-
264
- **Rules for the output:**
265
- - Set `curatedAt` to the current ISO timestamp
266
- - Only include types that have real CMS data
267
- - For component mocks: include only fields present in the source data
268
- - For collection mocks: always include `mock` and `cards`
269
- - Rich Text body fields must be `{ "json": <Document> }` — copy as-is
270
- - Visual fields must include `width`, `height`, AND `url` — never strip `url`
271
- - Include `widthPercent` when present on media/externalVideo entries
272
- - Include `otherMedia` when present — copy the full array including `url` and `widthPercent`
273
- - Do NOT invent or modify content — use the real data from the examples file
274
- - Include `backgroundColour` and `textColour` where the source has them
275
- - For cards: include ALL fields present in source, including `backgroundColour`, `textColour`, `links`
276
-
277
- ### Step 6 — Verify
278
-
279
- After writing, briefly confirm:
280
- - The file is valid JSON
281
- - Component and collection counts look reasonable (non-zero)
282
- - Key types (Hero, main collections) have entries
283
- - Visual fields include `url` properties
284
-
285
- ---
286
-
287
- ## Output files
288
-
289
- | File | Location | Committed |
290
- |------|----------|-----------|
291
- | `showcase-examples.json` | `src/generated/showcase-examples.json` | No (gitignored) |
292
- | `showcase-mocks-draft.json` | `src/generated/showcase-mocks-draft.json` | No (gitignored) |
293
- | `accepted-variants/` | `src/generated/cms-discovery/accepted-variants/{components\|collections\|externals}/` | No (gitignored) |
294
- | `showcase-mocks.json` | `src/generated/showcase-mocks.json` | Yes |
295
-
296
- ---
297
-
298
- ## How the showcase uses this
299
-
300
- The showcase uses a **two-layer model**:
301
-
302
- 1. **Base: mock data** — `showcase-mocks.json` is merged over inline registration mocks via
303
- `mergeShowcaseMocks()` from `@se-studio/core-ui`. Curated data takes precedence; types without
304
- curated data fall back to their inline `mock:` in the registration.
305
-
306
- 2. **Patch: URL params** — Any control field in the URL (e.g. `?backgroundColour=Navy`) overrides
307
- the mock. The control bar encodes only values that differ from the mock baseline.
308
-
309
- `?clean=true` skips mock data entirely and uses the default showcase control state only.
310
-
311
- ---
312
-
313
- ## External project setup (seskills)
314
-
315
- ### Installing skills
316
-
317
- For standalone projects not in the monorepo, install or update skills via:
318
-
319
- ```bash
320
- seskills sync
321
- ```
322
-
323
- This copies all SE Studio cursor skills (including this one) into the project's `.agents/skills/`
324
- directory. The `seskills` binary is provided by `@se-studio/project-build`.
325
-
326
- ### Auto-sync on package update
327
-
328
- Add a `postinstall` script to the project's `package.json` so skills automatically sync
329
- whenever `pnpm install` is run (including after bumping `@se-studio/project-build`):
330
-
331
- ```json
332
- "postinstall": "seskills sync --if-installed"
333
- ```
334
-
335
- The `--if-installed` flag makes the sync a no-op if run inside the monorepo itself
336
- (where `project-build` is a workspace package, not an installed npm package), so it
337
- is safe to add to any project.
338
-
339
- ### Script paths
340
-
341
- The CLI scripts are available as installed binaries after `npm install @se-studio/project-build`.
342
- Both `generate-showcase-data` and `generate-showcase-mocks` read `.env.local` from `process.cwd()`,
343
- so run them from the project root.
@@ -1,195 +0,0 @@
1
- ---
2
- name: handling-media
3
- description: Guide for using images, videos, and animations in marketing sites using the ResponsiveVisual and VisualComponent systems.
4
- license: Private
5
- metadata:
6
- author: se-core-product
7
- version: "1.0.0"
8
- ---
9
-
10
- # Handling Media
11
-
12
- This project uses a unified media system to handle images, videos, and animations efficiently.
13
-
14
- ## Core Components
15
-
16
- ### 1. `ResponsiveVisual` (or `VisualComponent`)
17
-
18
- This is the main component for rendering media from Contentful. It handles:
19
- * Responsive image sources (desktop/mobile).
20
- * Format optimization (WebP/AVIF).
21
- * Video auto-play/looping.
22
- * Lottie animations.
23
- * Lazy loading & Priority hints.
24
-
25
- ```typescript
26
- import VisualComponent from '@/framework/VisualComponent';
27
- // or
28
- import { Visual } from '@se-studio/core-ui';
29
- ```
30
-
31
- ## Usage Pattern
32
-
33
- ### Basic Usage
34
-
35
- ```typescript
36
- <VisualComponent
37
- visual={field.visual}
38
- className="w-full h-auto"
39
- />
40
- ```
41
-
42
- ### Responsive Sizing (`visualSizes`)
43
-
44
- You **MUST** provide `visualSizes` to ensure the browser loads the correct image size. This uses the `sizes` attribute.
45
-
46
- ```typescript
47
- import { calculateVisualSizes } from '@se-studio/core-ui';
48
-
49
- // Example: Full width on mobile, 50% width on laptop
50
- const sizes = calculateVisualSizes(1, { laptop: 0.5 });
51
-
52
- <VisualComponent
53
- visual={visual}
54
- visualSizes={sizes}
55
- />
56
- ```
57
-
58
- * `1`: 100vw (Mobile default)
59
- * `laptop: 0.5`: 50vw (Laptop breakpoint)
60
-
61
- ### visualSizes Must Mirror Col-Span
62
-
63
- `visualSizes` **must** match the visual's layout (col-span, container width). The browser uses these values to pick the right image size.
64
-
65
- * **Rule**: `col-span-N` in a 12-col grid → use `N/12` (e.g. 6 cols → 0.5, 5 cols → 5/12).
66
- * **Full width** (`col-span-full`) → use `1`.
67
- * **First arg** = mobile/default; breakpoint keys (`laptop`, `tablet`, `desktop`) = that breakpoint.
68
- * **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 })`.
69
- * **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).
70
- * **Example table**:
71
-
72
- | Layout | visualSizes |
73
- |--------|-------------|
74
- | Full width | `(1)` |
75
- | 6 cols on laptop, full on mobile | `(1, { laptop: 0.5 })` |
76
- | 5 cols on laptop, full on mobile | `(1, { laptop: 5/12 })` |
77
- | 2 cols in 12 on laptop, half on mobile | `(0.5, { laptop: 2/12 })` |
78
- | Small icon (~96px) | `(0.25)` |
79
-
80
- ### CMS Width & Position (`widthPercent`, `horizontalPosition`)
81
-
82
- Visuals in Contentful can have a `widthPercent` (e.g. 50%) and `horizontalPosition` (Left / Middle / Right). These control how wide the visual renders on laptop+ and where it aligns within its container. **How these fields are applied depends on the component rendering the visual.**
83
-
84
- **Key principle**: The `Visual` component is a "fill my container" renderer — it does **not** apply width constraints itself. Width and position are always the responsibility of the wrapping component.
85
-
86
- #### Which components handle it automatically
87
-
88
- * **`VisualComponent`** (framework, `@/framework/VisualComponent`): Handles `widthPercent` and `horizontalPosition` in both embedded and non-embedded modes. Also adjusts `visualSizes` so the browser fetches an appropriately sized image.
89
- * **`ResponsiveVisual`** (core-ui): Wraps the `Visual` in a div that applies `--image-width` and horizontal positioning. Components using `ResponsiveVisual` get this for free.
90
-
91
- #### Custom components using `Visual` directly
92
-
93
- If your component renders `Visual` directly and the visual may have a `widthPercent`, you must handle it yourself:
94
-
95
- 1. **Wrap in a positioning div** using helpers from `core-ui`:
96
-
97
- ```typescript
98
- import { getVisualWidthPercent } from '@se-studio/core-data-types';
99
- import {
100
- calculateHorizontalPositionClassName,
101
- calculateImageWidthStyleVariable,
102
- calculateVisualSizes,
103
- Visual,
104
- cn,
105
- } from '@se-studio/core-ui';
106
-
107
- const imageWidthStyle = calculateImageWidthStyleVariable(visual);
108
- const imageHorizontalPosition = imageWidthStyle
109
- ? calculateHorizontalPositionClassName(visual)
110
- : undefined;
111
-
112
- <div
113
- className={cn(
114
- 'w-full',
115
- imageHorizontalPosition,
116
- imageWidthStyle && 'laptop:w-(--image-width)',
117
- )}
118
- style={imageWidthStyle}
119
- >
120
- <Visual visual={visual} visualSizes={visualSizes} />
121
- </div>
122
- ```
123
-
124
- 2. **Factor width into `visualSizes`** so the browser doesn't over-fetch:
125
-
126
- ```typescript
127
- const widthPercent = getVisualWidthPercent(visual);
128
- const laptopRatio = widthPercent ? widthPercent / 100 : undefined;
129
- const visualSizes = laptopRatio
130
- ? calculateVisualSizes(1, { laptop: laptopRatio })
131
- : calculateVisualSizes(1);
132
- ```
133
-
134
- #### Collections with multiple visuals
135
-
136
- Collections like `SeparatedVisualsCollection` may interpret `widthPercent` differently — as relative proportions between visuals rather than absolute percentages. The collection controls the layout and passes the computed slot width to `visualSizes`. Don't apply the standard wrapper pattern blindly in collections; match `visualSizes` to the actual rendered slot width.
137
-
138
- ### LCP Optimization (`calculateImagePriority`)
139
-
140
- For the Hero component (or whatever is at the top of the page), you must prioritize the image load to improve LCP (Largest Contentful Paint).
141
-
142
- Use `calculateImagePriority(index)` where `index` is the component's position on the page.
143
-
144
- ```typescript
145
- import { calculateImagePriority } from '@se-studio/core-ui';
146
-
147
- <VisualComponent
148
- visual={visual}
149
- {...calculateImagePriority(index)}
150
- />
151
- ```
152
-
153
- If `index` is `0`, this sets `priority={true}` (or `fetchPriority="high"`). If `index > 0`, it defaults to lazy loading.
154
-
155
- ### Analytics Tracking
156
-
157
- Pass `componentLabel` (usually `cmsLabel`) and `analyticsContext` to enable click tracking on media elements (if they are linked).
158
-
159
- ```typescript
160
- <VisualComponent
161
- visual={visual}
162
- componentLabel={cmsLabel}
163
- analyticsContext={contentContext.analyticsContext}
164
- />
165
- ```
166
-
167
- ## Media Types
168
-
169
- The `IResponsiveVisual` type (from `@se-studio/core-data-types`) supports:
170
-
171
- 1. **Image**: Standard Contentful image asset.
172
- 2. **Video**: Hosted video file (mp4/webm). The component handles `<video>` tag rendering with autoplay/loop/muted attributes suitable for background videos.
173
- 3. **Animation**: Lottie JSON file. Renders using a Lottie player.
174
-
175
- The component automatically detects the type and renders the appropriate element.
176
-
177
- ## Mobile Specific Visuals
178
-
179
- Contentful models often support a separate `mobileVisual` field. The `VisualComponent` handles switching between them using `<picture>` tags or CSS media queries internally.
180
-
181
- You typically pass the combined object or handle it via props if the component exposes both:
182
-
183
- ```typescript
184
- // If your component merges them into one responsive object before rendering:
185
- <VisualComponent visual={combinedVisual} />
186
- ```
187
-
188
- Or if using raw fields:
189
-
190
- ```typescript
191
- <VisualComponent
192
- visual={visual}
193
- mobileVisual={mobileVisual}
194
- />
195
- ```
@@ -1,83 +0,0 @@
1
- ---
2
- name: lib-cms-structure
3
- description: Guide for the lib directory structure in SE Core Product CMS apps. Use when setting up lib/, migrating from contentful-config, or adding new CMS configuration.
4
- license: Private
5
- metadata:
6
- author: se-core-product
7
- version: "1.0.0"
8
- ---
9
-
10
- # Lib Directory Structure
11
-
12
- Reference apps: **example-se2026**, **example-brightline**, **example-om1**.
13
-
14
- ## File Responsibilities
15
-
16
- | File | Client-safe? | Purpose |
17
- |------|--------------|---------|
18
- | `cms.ts` | Yes | Types, buildComponentRecord / buildCollectionRecord / buildExternalRecord (array → Record), then build*Maps from those Records, createConverterContext |
19
- | `cms-server.ts` | No (server-only) | createAppHelpers, buildOptions, getContentfulConfig, projectRendererConfig |
20
- | `config.ts` | Yes | isProduction, isDevelopment |
21
- | `server-config.ts` | No | draftOnly, videoPrefix, baseUrl, revalidationSecret |
22
- | `constants.ts` | Yes | ARTICLES_BASE, TAGS_BASE, PEOPLE_BASE, enable flags, customer name |
23
- | `registrations.ts` | Yes | componentRegistrationsList, collectionRegistrationsList, externalComponentRegistrationsList (arrays) |
24
- | `SizingInformation.ts` | Yes | getSizingInformation for dynamic heading sizes |
25
-
26
- ## Server vs Client Boundary
27
-
28
- - **cms-server.ts** has `import 'server-only'`. Never import it in `'use client'` components.
29
- - **cms.ts** is client-safe: types, maps, converter context factory (no env access).
30
- - **registrations.ts** imports from cms.ts and project components; keep it client-safe.
31
-
32
- ## constants.ts Shape
33
-
34
- ```typescript
35
- export const ARTICLES_SLUG = 'articles'; // or 'learning-hub'
36
- export const TAGS_SLUG = 'tags';
37
- export const PEOPLE_SLUG = 'people';
38
- export const DEFAULT_TOPIC = 'other';
39
-
40
- export const ARTICLES_BASE = `/${ARTICLES_SLUG}`;
41
- export const TAGS_BASE = `/${TAGS_SLUG}`;
42
- export const PEOPLE_BASE = `/${PEOPLE_SLUG}`;
43
-
44
- export const customerName = '...';
45
- export const applicationName = '...';
46
- export const siteTitle = '...';
47
- export const siteDescription = '...';
48
- export const enablePerson = false;
49
- export const enablePeopleIndex = false;
50
- export const enableTag = false;
51
- export const enableTagsIndex = false;
52
- ```
53
-
54
- ## Data Flow
55
-
56
- ```
57
- registrations.ts (*RegistrationsList arrays)
58
- → cms.ts (build*Record from arrays, then build*Maps)
59
- → builds maps → cms-server.ts
60
-
61
- projectRendererConfig
62
- ```
63
-
64
- Add new components/collections to the appropriate *RegistrationsList array in `registrations.ts`. The `cms.ts` imports those arrays, builds Records via `buildComponentRecord` / `buildCollectionRecord` / `buildExternalRecord` (which enforce that every CMS type has a registration), then builds the maps used by `cms-server.ts`.
65
-
66
- ## Circular Dependency: Do Not Import cms-server in Components/Collections
67
-
68
- Components and collections in the registration chain (imported by `registrations.ts`) must **not** import from `cms-server` directly. Doing so creates a circular dependency (cms-server → cms → registrations → components → cms-server) that causes TDZ errors during RSC serialization.
69
-
70
- **Instead**, use the helpers from `@se-studio/core-ui`:
71
-
72
- - `getPreviewFieldProps(rendererConfig, id, fieldId)` – for field preview props
73
- - `getPreviewResponsiveVisualFieldProps(rendererConfig, id, visualFieldId, mobileVisualFieldId)` – for responsive visuals
74
- - `rendererConfig.previewHelpers?.getPreviewParentProps?.(information)`
75
- - `rendererConfig.fetchHelpers?.getAllArticleLinks?.()`
76
- - `rendererConfig.fetchHelpers?.getRelatedArticles?.(information, contentContext, count)`
77
-
78
- These are passed via `projectRendererConfig` in `cms-server.ts`. `Section` and `SectionLinks` accept `previewHelpers` / `rendererConfig` props. See `docs/SERVER_CLIENT_BOUNDARIES.md`.
79
-
80
- ## See Also
81
-
82
- - **register-cms-features** – Adding components and collections
83
- - **cms-routes-and-appshared** – Route structure and appShared