@se-studio/skills 1.9.10 → 1.9.15
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 +30 -0
- package/package.json +1 -1
- package/references/agent-session/customer-agents-block.md +1 -1
- package/references/agent-session/customer-architecture.mdc +10 -0
- package/references/agent-session/customer-code-review.md +15 -1
- package/references/contentful-cms-cms-guidelines/html-component-authoring.md +2 -0
- package/skills/coding-discipline/SKILL.md +1 -1
- package/skills/contentful-cms-core/SKILL.md +3 -3
- package/skills/contentful-cms-regenerate-editor-pack/SKILL.md +6 -2
- package/skills/screaming-frog-audit/SKILL.md +14 -0
- package/skills/se-marketing-sites-cms-routes-and-appshared/SKILL.md +6 -4
- package/skills/se-marketing-sites-create-collection/SKILL.md +9 -0
- package/skills/se-marketing-sites-create-component/SKILL.md +13 -2
- package/skills/se-marketing-sites-create-page/SKILL.md +16 -14
- package/skills/se-marketing-sites-customer-simplicity/SKILL.md +42 -0
- package/skills/se-marketing-sites-styling-system/SKILL.md +18 -4
- package/skills/site-workflows-agent-session/SKILL.md +19 -2
- package/skills/site-workflows-new-project/SKILL.md +5 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# @se-studio/skills
|
|
2
2
|
|
|
3
|
+
## 1.9.15
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- f03f1f1: Document the weekly production Screaming Frog fleet audit.
|
|
8
|
+
|
|
9
|
+
## 1.9.14
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 3d4f180: State the marketing-route and layout rules in the customer architecture block, the session skill, and the page and styling skills. A new URL is a Contentful slug. Frame width is not a max-width, and a missing text style stops the plan instead of becoming `leading-[…]`.
|
|
14
|
+
|
|
15
|
+
## 1.9.13
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- b47c1c2: Implement se-core #252 anti-Webflow-port BLOCKERs plus Nick simplicity rules (no RTF flatten, links as-is, no hardcoded visitor copy, Tailwind over CSS islands, fail closed). Add skill `se-marketing-sites-customer-simplicity`, wire from agent-session, and soften globals.css / customCss escape hatches.
|
|
20
|
+
|
|
21
|
+
## 1.9.12
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- fbb6952: Document Option C editor-pack publish via customer CI (reusable GitHub Actions workflow). Agents regenerate and commit packs only; they do not run `gh release create` unless Nick asks.
|
|
26
|
+
|
|
27
|
+
## 1.9.11
|
|
28
|
+
|
|
29
|
+
### Patch Changes
|
|
30
|
+
|
|
31
|
+
- 3ecda13: Document that different UI/behaviour needs distinct `componentType` / `collectionType`; `cmsLabel` is for authors (+ trackingLocation), never a runtime layout/renderer switch. Update create-component, create-collection, and contentful-cms-core (synced into contentful-cms bundled `core` skill).
|
|
32
|
+
|
|
3
33
|
## 1.9.10
|
|
4
34
|
|
|
5
35
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -28,7 +28,7 @@ Before non-trivial code, run the placement checklist (in the skill). Summary:
|
|
|
28
28
|
|
|
29
29
|
| Belongs in… | Examples |
|
|
30
30
|
|-------------|----------|
|
|
31
|
-
| **This repo** (`src/project/*`, `cms-edit/**`) | Brand components, styling,
|
|
31
|
+
| **This repo** (`src/project/*`, `cms-edit/**`) | Brand components, styling, editor-pack, and `src/lib/marketing-routes.json` (which article-type and person-type folders exist). A new URL is a Contentful slug, not a new `page.tsx`. |
|
|
32
32
|
| **Customer shared package** (if monorepo) | Consent/analytics shared across sites in this customer |
|
|
33
33
|
| **`se-core-product`** (`@se-studio/*`) | Fixes/features needed by 2+ sites, CMS infrastructure |
|
|
34
34
|
|
|
@@ -24,8 +24,18 @@ Source of truth: `se-core-product` `docs/PHILOSOPHY.md`. Code review: `CODE_REVI
|
|
|
24
24
|
|
|
25
25
|
- Keep T0/T1 skeleton files thin; document deviations in the site README.
|
|
26
26
|
- Use core route handlers (`generatePage`, robots, sitemaps, etc.). Do not reimplement.
|
|
27
|
+
- A new marketing URL is a Contentful page slug (use `indexed: false` for an experiment). Do not add `src/app/**/page.tsx` for it. App Router pages are the CMS catch-all, a folder named in `src/lib/marketing-routes.json` for an article type or a person type, and the fixed misc files (page-test, preview, sitemap, robots, markdown, download, og, api, cms-dev).
|
|
28
|
+
- Every marketing block is `<Section>` with `content-cols-grid`. Width is `col-span-*`, `max-w-cols-N`, or `max-w-cols-gap-N`. Type is a `fontTable` class (`h1`, `p2`, `sizingInformation.*`). Vertical space is `section-spacing` on `Section`.
|
|
29
|
+
- Figma stays the source for layout, copy, colour, and type when a text style is set. Implement with the grid and the font table. Do not paste MCP arbitrary classes.
|
|
30
|
+
- Plan-time stops: the frame width (1440, 1920, whatever the artboard is) is not `max-w-[…]`. Type with no text style (`leading-[1.2]`, raw `text-[32px]`) means the designer did not specify the font — name the node and wait. Do not pick a class and continue.
|
|
27
31
|
- Mobile-first Tailwind. Preserve heading hierarchy. Size visuals with core helpers. Avoid duplicate mobile/desktop markup for the same content.
|
|
28
32
|
- UI changes: early Vercel preview (mobile + laptop) → Nick visual → full breakpoints including oversize (~1920+) before deep polish/code review.
|
|
33
|
+
- **Remakes are not Webflow reconstruction** (PHILOSOPHY §5a / `se-marketing-sites-customer-simplicity`):
|
|
34
|
+
- CMS entry → registered component/collection only; **fail closed** when a field is empty (omit UI / fix CMS — never invent from the live site).
|
|
35
|
+
- Body/`additionalCopy` via `RtfOrString` — no RTF→plain flatten for layout.
|
|
36
|
+
- CMS `links` as-is with standard link helpers — no invented roles unless Nick asks.
|
|
37
|
+
- No hardcoded visitor copy, live URLs, or brand media fallbacks in TS.
|
|
38
|
+
- Tailwind + design tokens over CSS islands; do not grow Webflow-ported page CSS. `globals.css` / HtmlComponent `customCss` for true one-offs or shared primitives only.
|
|
29
39
|
|
|
30
40
|
## Caching / performance / images
|
|
31
41
|
|
|
@@ -52,14 +52,28 @@ Run all five lenses. Skip a lens only when the diff clearly cannot touch it (say
|
|
|
52
52
|
- Consent granted by default where a CMP decides, or bypassing site consent gating.
|
|
53
53
|
- Forms: preview posting to production CRM/forms destinations or GTM, or bypassing server-side submit.
|
|
54
54
|
- Hard-coded heading skips, `Visual` without size helpers, or needless duplicate mobile/desktop content.
|
|
55
|
+
- A new `src/app/**/page.tsx` for a marketing URL. That URL is a Contentful slug (often `indexed: false` for an experiment). Allowed app pages: the CMS catch-all, an article type or person type named in `src/lib/marketing-routes.json`, and the fixed misc set (page-test, preview, sitemap, robots, markdown, download, og, api, cms-dev).
|
|
56
|
+
- Arbitrary layout standing in for the grid or an unspecified text style: `max-w-[1440px]` or `max-w-[1920px]` (that number is the Figma frame, not a max-width), `leading-[…]` / `text-[32px]` with no `fontTable` class, section padding via `py-[…]` instead of `<Section>`, `content-cols-grid`, and `max-w-cols-N`. Name the Figma node in the plan and wait. Do not guess a style and do not paste MCP classes.
|
|
55
57
|
- Failing typecheck, lint, or tests; new behaviour with no test where the site already tests that layer.
|
|
56
58
|
- Smoke/discovery/`server-config` hacks to unblock deploy smoke (belongs in `@se-studio/site-check`).
|
|
59
|
+
- **Remake / port simplicity** (PHILOSOPHY §5a / skill `se-marketing-sites-customer-simplicity`):
|
|
60
|
+
- Stub or heading-match fallback as the live renderer; unfinished types must stay unregistered or preview-only.
|
|
61
|
+
- Catalogue fetch (`getAllArticleLinks` / `getAllPersonLinks` / walking another page) inside a component or layout.
|
|
62
|
+
- Layout/behaviour multiplex on `cmsLabel` / heading / `anchor` (type ≠ label).
|
|
63
|
+
- Flattening body/`additionalCopy` RTF → plain strings or paragraph heuristics to drive layout (use `RtfOrString`).
|
|
64
|
+
- Inventing or filtering CMS `links` into roles / special chrome unless Nick explicitly asked.
|
|
65
|
+
- Hardcoded visitor copy, live URLs, CDN paths, or brand media fallbacks in TS — fix CMS instead.
|
|
66
|
+
- New Webflow/FlowKit CSS dumps or growing page CSS islands (`etf.css`-style, `fk-*`, minified sheets) for layout; prefer Tailwind + tokens. `globals.css` / `customCss` only for true one-offs or shared primitives.
|
|
67
|
+
- Filling missing CMS by inventing from the live site (must **fail closed**: omit UI or fix CMS).
|
|
68
|
+
- Second public URL system or custom App Router page for a type `generatePage` already covers.
|
|
69
|
+
- Mixed `@se-studio/*` majors on one site without an aligned bump plan.
|
|
57
70
|
|
|
58
71
|
**NIT**
|
|
59
72
|
|
|
60
73
|
- Prefer existing core components over one-offs.
|
|
61
74
|
- Don’t rename existing tracking events only to match other sites.
|
|
62
75
|
- Clearer names, smaller functions, docs polish.
|
|
76
|
+
- Pixel-perfect vs Figma before the early visual gate (not a merge blocker early). Webflow remakes follow CMS→component + tokens, not pixel CSS dumps.
|
|
63
77
|
|
|
64
78
|
---
|
|
65
79
|
|
|
@@ -70,7 +84,7 @@ If the PR changes UI, confirm the session followed agent-session visual phases:
|
|
|
70
84
|
1. **Early:** Vercel preview, mobile (~390) + laptop (~1280), stopped for Nick’s visual review.
|
|
71
85
|
2. **Full (after Nick is happy):** tablet (~768), laptop (~1280), **oversize (~1920+)**, plus mobile — flag overflow, stretched heroes, broken grids.
|
|
72
86
|
|
|
73
|
-
Do not treat “pixel-perfect vs Figma” as a merge blocker before the early visual gate completes.
|
|
87
|
+
Do not treat “pixel-perfect vs Figma” as a merge blocker before the early visual gate completes. Remakes from live Webflow/HTML are **not** a fidelity chase against the old site — implement CMS fields with tokens; flag invented structure as **BLOCKER** above.
|
|
74
88
|
|
|
75
89
|
---
|
|
76
90
|
|
|
@@ -11,6 +11,8 @@ metadata:
|
|
|
11
11
|
|
|
12
12
|
`HtmlComponent` is a CMS content type that renders developer-authored HTML directly into the page. It bypasses the standard component registration system and is intended for one-off or highly custom layouts that the structured component library cannot produce.
|
|
13
13
|
|
|
14
|
+
**Last resort, not the default remake path.** Prefer a registered `componentType` / `collectionType` + Tailwind tokens. Do not use HtmlComponent + `customCss` to reconstruct a Webflow page when a registered component would work. See `se-marketing-sites-customer-simplicity` and PHILOSOPHY §5a.
|
|
15
|
+
|
|
14
16
|
---
|
|
15
17
|
|
|
16
18
|
## Before You Start
|
|
@@ -299,7 +299,7 @@ export const HeroRenderer: ComponentRenderer<ProjectConfig> = ({ information })
|
|
|
299
299
|
|
|
300
300
|
## Code Style Requirements
|
|
301
301
|
|
|
302
|
-
- **Styling**: Tailwind
|
|
302
|
+
- **Styling**: Tailwind utilities + design tokens first. Do not use CSS modules (`*.module.css`). Prefer classes in TSX over new CSS. `src/app/globals.css` is for **shared primitives only** (keyframes, RTF element maps, true design-system utilities) — not per-page Webflow/layout reconstruction. Growing page CSS islands is review debt (see `se-marketing-sites-customer-simplicity`).
|
|
303
303
|
- **Biome** for linting/formatting (not ESLint/Prettier)
|
|
304
304
|
- Single quotes, semicolons, trailing commas
|
|
305
305
|
- `import type` for type-only imports
|
|
@@ -218,8 +218,8 @@ Based on the SE Studio content model:
|
|
|
218
218
|
### Component fields
|
|
219
219
|
| Field | Type | Notes |
|
|
220
220
|
|-------|------|-------|
|
|
221
|
-
| `cmsLabel` | string | Internal name (required) |
|
|
222
|
-
| `componentType` | string | Type discriminator (e.g. `HeroSimple`) |
|
|
221
|
+
| `cmsLabel` | string | Internal name for authors in Contentful (required). Not a runtime layout/renderer switch — never branch code on it. |
|
|
222
|
+
| `componentType` | string | Type discriminator for renderer lookup (e.g. `HeroSimple`). Different UI/behaviour needs a distinct value. |
|
|
223
223
|
| `heading` | string | Main heading (only shown when `showHeading` is true) |
|
|
224
224
|
| `showHeading` | boolean | Whether to display the heading |
|
|
225
225
|
| `preHeading` | string | Text above the heading |
|
|
@@ -234,7 +234,7 @@ Based on the SE Studio content model:
|
|
|
234
234
|
Same as Component plus:
|
|
235
235
|
| Field | Type | Notes |
|
|
236
236
|
|-------|------|-------|
|
|
237
|
-
| `collectionType` | string | Type discriminator (e.g. `CardGrid`) |
|
|
237
|
+
| `collectionType` | string | Type discriminator for renderer lookup (e.g. `CardGrid`). Different UI/behaviour needs a distinct value; do not switch on `cmsLabel`. |
|
|
238
238
|
|
|
239
239
|
### Page fields
|
|
240
240
|
| Field | Type | Notes |
|
|
@@ -91,10 +91,14 @@ git add cms-edit/editor-pack # or cms-edit/<site>/editor-pack
|
|
|
91
91
|
git commit -m "chore(cms-edit): regenerate editor pack"
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
-
## Step 6 — Publish (commit + push
|
|
94
|
+
## Step 6 — Publish (commit + push; CI owns GitHub Releases)
|
|
95
95
|
|
|
96
96
|
**Absolute rule for agents:** hosted MCP is **never** published via `vercel deploy`, `pnpm cms-edit:deploy*`, or `deploy-cms-edit-host.sh`. Commit and push is the only deploy path for customer repos with `cms-edit/host/`.
|
|
97
97
|
|
|
98
|
+
**Option C (shared multi-tenant host):** Customer CI publishes the committed pack as a GitHub Release (`editor-pack.tar.gz`) via the reusable workflow `Something-Else-Studio/se-core-product/.github/workflows/cms-edit-pack-publish.yml`. Agents do **not** run `gh release create` (or treat the printed command from `cms-edit host pack-publish` as something to execute) unless Nick explicitly asks. Do **not** regenerate the pack in CI — publish the committed `editor-pack/` only. Tags are immutable (`cms-edit-pack-<projectKey>-v<version>`); bump version for a new Release, then update the host registry `packTag` when intentional.
|
|
99
|
+
|
|
100
|
+
See `packages/contentful-cms/HOSTED.md` (Option C section) for the caller workflow sketch.
|
|
101
|
+
|
|
98
102
|
### Customer repo with `cms-edit/host/` (SE Studio, Pedestal, Headwater, Brightline, …)
|
|
99
103
|
|
|
100
104
|
Commit `editor-pack/` (and any other `cms-edit/**` changes) and push **`develop`**. Hosted MCP Production is the marketing production branch (`main`, HSD `production`). Merge there only after ask + confirm (`production-merge.md`). `ignoreCommand` skips `develop` and feature refs.
|
|
@@ -108,7 +112,7 @@ Do **not** run `pnpm cms-edit:deploy` or `vercel deploy` after this step.
|
|
|
108
112
|
|
|
109
113
|
### Customers without `cms-edit/host/` in their repo
|
|
110
114
|
|
|
111
|
-
Rare layout — coordinate with the repo owner. Agents still must not run deploy scripts unless explicitly asked.
|
|
115
|
+
Rare layout — coordinate with the repo owner. Agents still must not run deploy scripts unless explicitly asked. For Option C tenants, pack publish still goes through customer CI → GitHub Release (same reusable workflow), not a local `gh release create`.
|
|
112
116
|
|
|
113
117
|
## Homepage slug reminder
|
|
114
118
|
|
|
@@ -59,6 +59,20 @@ Prioritized P0–P3 report from a single crawl export.
|
|
|
59
59
|
|
|
60
60
|
---
|
|
61
61
|
|
|
62
|
+
## Fleet production audit
|
|
63
|
+
|
|
64
|
+
From se-core-product, crawl every marketing production site and write P0–P3 reports. One site at a time. Quit the Screaming Frog GUI first.
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
pnpm seo:screaming-frog:fleet # crawl + audit
|
|
68
|
+
pnpm seo:screaming-frog:fleet -- --list
|
|
69
|
+
node scripts/screaming-frog-fleet.mjs --install-agent
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Reports land in `~/spider/fleet-audits/<YYYY-MM-DD>/`. The command does not pass `--tag`, so it does not replace a deployment `content` baseline. `--install-agent` loads a user LaunchAgent (`studio.se.screaming-frog-fleet`) for Sunday 22:00 local time.
|
|
73
|
+
|
|
74
|
+
Start URL: the manifest `production` profile. When that profile is a `*.vercel.app` alias and cms-edit `productionSiteUrl` is a public host, the public host is crawled. Eagle stays on its configured Vercel production URL. Preview-only issue downgrades (noindex, preview robots) are not applied.
|
|
75
|
+
|
|
62
76
|
## Other commands
|
|
63
77
|
|
|
64
78
|
```bash
|
|
@@ -7,6 +7,8 @@ description: "Guide for the (cms-routes) route group and appShared pattern. Use
|
|
|
7
7
|
|
|
8
8
|
Reference app: **example-empty** (this monorepo). Customer sites with fuller route sets: see `docs/RELATED_PROJECTS.md` (e.g. OM1 uses `resources/`, `team/`, `topics/` instead of `articles/`, `people/`, `tags/`).
|
|
9
9
|
|
|
10
|
+
Do not add a `page.tsx` for a marketing URL. That URL is a Contentful slug on the catch-all. Extra folders are only article types and person types listed in `src/lib/marketing-routes.json`.
|
|
11
|
+
|
|
10
12
|
## Route Group: (cms-routes)
|
|
11
13
|
|
|
12
14
|
All CMS-driven pages live under `src/app/(cms-routes)/`. The layout enables dynamic params:
|
|
@@ -29,9 +31,9 @@ export default function CmsRoutesLayout({ children }: { children: React.ReactNod
|
|
|
29
31
|
| `/{slug1}/{slug2}/...` | `[level1]/[...slugs]/page.ts` | Multi-level pages |
|
|
30
32
|
| `/articles/` | `articles/page.ts` | Articles index (uses ARTICLES_BASE) |
|
|
31
33
|
| `/articles/{type}/` | `articles/[articleType]/page.ts` | Article type index |
|
|
32
|
-
| `/articles/{type}/{tag}/` | `articles/[articleType]/[tag]/page.ts` | Article type + tag index |
|
|
33
|
-
| `/articles/{type}/{tag}/{article}/` | `articles/[articleType]/[tag]/[...slugs]/page.ts` | Individual article |
|
|
34
|
-
| `/tags/`, `/tags/{tag}/` | `tags/` | Tag index
|
|
34
|
+
| `/articles/{type}/{tag}/` | `articles/[articleType]/[tag]/page.ts` | Article type + tag index. Only when that base sets `tagInPath: true`. Hand-written `generateArticleTypeTag*` page. |
|
|
35
|
+
| `/articles/{type}/{tag}/{article}/` | `articles/[articleType]/[tag]/[...slugs]/page.ts` | Individual article with a tag segment. Same `tagInPath` rule. |
|
|
36
|
+
| `/tags/`, `/tags/{tag}/` | `tags/` | Tag index when `tags: true` |
|
|
35
37
|
| `/people/`, `/people/{person}/` | `people/` | People (if enabled) |
|
|
36
38
|
|
|
37
39
|
Base paths come from `@/lib/constants` (e.g. ARTICLES_BASE = `/learning-hub` or `/articles`).
|
|
@@ -97,7 +99,7 @@ export default async function (props: PageProps<'/[level1]'>) {
|
|
|
97
99
|
}
|
|
98
100
|
```
|
|
99
101
|
|
|
100
|
-
|
|
102
|
+
A dynamic `articles` route uses `converterContext.urlCalculators` (`article`, `articleType`, `articleTypeTag`). Import `converterContext` from `@/lib/converter-context` when that module exists (so route files don't pull in cms-server); otherwise from `@/lib/cms-server`. A fixed article folder, and a dynamic base whose path is not `articles`, passes the path of that file (`/work/`, `/work/${articleSlug}/`). `article()` prefixes `ARTICLES_BASE` and, when primary tags are on, inserts `other`. That is a different URL from the file that was written. The generator does this. Hand-written `[tag]` pages still use `articleTypeTag`.
|
|
101
103
|
|
|
102
104
|
## See Also
|
|
103
105
|
|
|
@@ -289,3 +289,12 @@ export const MyCollectionRegistration = defineCollection({
|
|
|
289
289
|
* Pass server-rendered cards as `children` to the client wrapper.
|
|
290
290
|
7. **Register**:
|
|
291
291
|
* Add to `collectionRegistrationsList` in `src/lib/registrations.ts`. The `name` is defined only in your `defineCollection(...)` call.
|
|
292
|
+
8. **Type vs label (hard rule)**:
|
|
293
|
+
* New UI or behaviour → new Contentful `collectionType` enum value + registration. Never `if (cmsLabel)` / parse labels for layout or renderer choice.
|
|
294
|
+
* `cmsLabel` is for authors (and may pass to `trackingLocation`); it is not a runtime discriminator.
|
|
295
|
+
* Position/variant-only differences may share one Core under multiple `defineCollection` registrations; drive layout from `collectionType`.
|
|
296
|
+
9. **Simplicity (remakes / ports)**:
|
|
297
|
+
* Do **not** flatten item body fields for layout; use `<RtfOrString>`.
|
|
298
|
+
* Do **not** invent link roles from CMS `links` unless Nick asks.
|
|
299
|
+
* Prefer Tailwind tokens over CSS islands; empty fields → omit (**fail closed**).
|
|
300
|
+
* Load `se-marketing-sites-customer-simplicity` on remake tasks.
|
|
@@ -231,9 +231,10 @@ export const MyNewRegistration = defineComponent({
|
|
|
231
231
|
* Add `'use client'` to that file only.
|
|
232
232
|
* Import and use in Core component.
|
|
233
233
|
5. **Build Wrapper Component**:
|
|
234
|
-
* Wrap Core with `<Section
|
|
234
|
+
* Wrap Core with `<Section>` (`content-cols-grid`, `section-spacing`). Do not replace Section with `max-w-[1440px]` or `py-16`.
|
|
235
235
|
* Pass `componentName={componentType}` and `information`.
|
|
236
|
-
* Set layout
|
|
236
|
+
* Set layout with `col-span-*`, `max-w-cols-N`, or `max-w-cols-gap-N`.
|
|
237
|
+
* Type is a `fontTable` class or `sizingInformation.*`. A Figma frame width is not a max-width. A node with no text style (`leading-[1.2]`, raw `text-[32px]`) stops the plan — do not guess a class.
|
|
237
238
|
6. **Build Renderer**:
|
|
238
239
|
* Default export (short name).
|
|
239
240
|
* Wrap with `<UnusedChecker>`.
|
|
@@ -244,3 +245,13 @@ export const MyNewRegistration = defineComponent({
|
|
|
244
245
|
* Provide mock data for showcase.
|
|
245
246
|
8. **Register Component**:
|
|
246
247
|
* Add to `componentRegistrationsList` in `src/lib/registrations.ts`. The `name` is defined only in your `defineComponent(...)` call; do not duplicate it as a Record key.
|
|
248
|
+
9. **Type vs label (hard rule)**:
|
|
249
|
+
* New UI or behaviour → new Contentful `componentType` enum value + registration. Never `if (cmsLabel)` / parse labels for layout or renderer choice.
|
|
250
|
+
* `cmsLabel` is for authors (and may pass to `trackingLocation`); it is not a runtime discriminator.
|
|
251
|
+
* Position/variant-only differences may share one Core under multiple `defineComponent` registrations; drive layout from `componentType`.
|
|
252
|
+
10. **Simplicity (remakes / ports)**:
|
|
253
|
+
* Layers are the registration pattern — not an invitation to bespoke parsers.
|
|
254
|
+
* Do **not** flatten body/`additionalCopy` for layout; use `<RtfOrString>`.
|
|
255
|
+
* Do **not** invent or filter CMS `links` into roles unless Nick asks.
|
|
256
|
+
* Prefer Tailwind tokens over new `globals.css` layout rules; CSS islands are debt.
|
|
257
|
+
* Empty field → omit UI (**fail closed**). Load `se-marketing-sites-customer-simplicity` on remake tasks.
|
|
@@ -9,6 +9,18 @@ This guide explains how to create new pages and handle routing in the SE Core Pr
|
|
|
9
9
|
|
|
10
10
|
Reference app: **example-empty** (this monorepo). Customer implementations: see `docs/RELATED_PROJECTS.md`.
|
|
11
11
|
|
|
12
|
+
## Do not add a route for a marketing URL
|
|
13
|
+
|
|
14
|
+
A new URL is a Contentful page slug, served by the catch-all (`[level1]` and `[...slugs]`). An experiment is a CMS page with `indexed: false`, not a new folder under `src/app`.
|
|
15
|
+
|
|
16
|
+
App Router `page` files are only:
|
|
17
|
+
|
|
18
|
+
- the CMS catch-all
|
|
19
|
+
- a folder named in `src/lib/marketing-routes.json` for an article type or a person type (`node scripts/generate-marketing-routes.mjs <app> --write` writes the thin article index and detail wrappers; `[tag]` segments are hand-written when that base sets `tagInPath: true`)
|
|
20
|
+
- the fixed misc files (page-test, preview, sitemap, robots, markdown, download, og, api, cms-dev)
|
|
21
|
+
|
|
22
|
+
`pnpm skeleton:check` fails an extra `page.ts` once `marketing-routes.json` is present. Search and other non-page tools stay misc routes. They are not a second copy of a CMS page.
|
|
23
|
+
|
|
12
24
|
## Page Architecture
|
|
13
25
|
|
|
14
26
|
### 1. (cms-routes) Route Group
|
|
@@ -33,9 +45,9 @@ export default function CmsRoutesLayout({ children }: { children: React.ReactNod
|
|
|
33
45
|
| `/{slug1}/{slug2}/...` | `[level1]/[...slugs]/page.ts` | Multi-level pages |
|
|
34
46
|
| `/articles/` | `articles/page.ts` | Articles index (uses ARTICLES_BASE from constants) |
|
|
35
47
|
| `/articles/{type}/` | `articles/[articleType]/page.ts` | Article type index |
|
|
36
|
-
| `/articles/{type}/{tag}/` | `articles/[articleType]/[tag]/page.ts` | Article type + tag index |
|
|
37
|
-
| `/articles/{type}/{tag}/{article}/` | `articles/[articleType]/[tag]/[...slugs]/page.ts` | Individual article |
|
|
38
|
-
| `/tags/`, `/tags/{tag}/` | `tags/` | Tag index
|
|
48
|
+
| `/articles/{type}/{tag}/` | `articles/[articleType]/[tag]/page.ts` | Article type + tag index. Only when that base sets `tagInPath: true`. Hand-written `generateArticleTypeTag*` page. `--write` does not emit it. |
|
|
49
|
+
| `/articles/{type}/{tag}/{article}/` | `articles/[articleType]/[tag]/[...slugs]/page.ts` | Individual article with a tag segment. Same `tagInPath` rule. |
|
|
50
|
+
| `/tags/`, `/tags/{tag}/` | `tags/` | Tag index when `tags: true` |
|
|
39
51
|
| `/people/`, `/people/{person}/` | `people/` | People (if enabled) |
|
|
40
52
|
|
|
41
53
|
Base paths (e.g. `/articles` vs `/learning-hub`) come from `@/lib/constants`.
|
|
@@ -104,19 +116,9 @@ The appShared modules render content with:
|
|
|
104
116
|
|
|
105
117
|
For route files that only need `converterContext` or `buildInformation` (e.g. `generateStaticParams`, sitemap, path computation), import from `@/lib/converter-context` when that module exists, so you don't pull in cms-server.
|
|
106
118
|
|
|
107
|
-
## Creating a Specialized Route
|
|
108
|
-
|
|
109
|
-
For a route that behaves differently from standard CMS pages (e.g. search, dashboard):
|
|
110
|
-
|
|
111
|
-
1. Create the route under `(cms-routes)` or a separate route group.
|
|
112
|
-
2. Either create a new appShared module (if the pattern is reusable) or implement inline.
|
|
113
|
-
3. Use `getPageWithErrors`, `getArticleWithErrors`, etc. from `@/lib/cms-server`.
|
|
114
|
-
4. Use `projectRendererConfig` from `@/lib/cms-server`.
|
|
115
|
-
5. Render with `CmsContent` using `contents`, `rendererConfig`, and `pageContext`.
|
|
116
|
-
|
|
117
119
|
## Custom Layouts
|
|
118
120
|
|
|
119
|
-
|
|
121
|
+
A different chrome (for example no header) is a `layout.tsx` on a route that already exists. It is not a new URL. A new marketing URL is still a Contentful slug.
|
|
120
122
|
|
|
121
123
|
## Troubleshooting
|
|
122
124
|
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: se-marketing-sites-customer-simplicity
|
|
3
|
+
description: "Guardrail for customer marketing remakes and ports. Load on Webflow/HTML remake, match-live-site, or parity tasks: CMS to component only, fail closed, no RTF flatten, link inventing, CSS islands, or hardcoded copy."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Customer site simplicity (remakes / ports)
|
|
7
|
+
|
|
8
|
+
CMS field in → registered UI out. Do not reconstruct the live site.
|
|
9
|
+
|
|
10
|
+
Canonical: `docs/PHILOSOPHY.md` §5a. Review: `customer-code-review.md`. Session: `site-workflows-agent-session` (**Do not port Webflow / HTML pages**). Subtract first: `principle-subtract-before-you-add`. How to build a type: `se-marketing-sites-create-component` / `create-collection`.
|
|
11
|
+
|
|
12
|
+
## Do
|
|
13
|
+
|
|
14
|
+
- CMS entry → `componentType` / `collectionType` → Registration → Core on core route handlers
|
|
15
|
+
- Empty field → **omit** that UI (or fix CMS). Never invent from the live site
|
|
16
|
+
- Body / `additionalCopy` via `RtfOrString`
|
|
17
|
+
- CMS `links` as-is with `SectionLinks` / `TrackedLink` (or site equivalents)
|
|
18
|
+
- Tailwind + design tokens; `Visual` + `calculateVisualSizes`; `getSizingInformation`
|
|
19
|
+
|
|
20
|
+
## Do not (BLOCKER)
|
|
21
|
+
|
|
22
|
+
| Antipattern | Instead |
|
|
23
|
+
|-------------|---------|
|
|
24
|
+
| Stub / heading-match as live renderer | Full layers, or stay unregistered |
|
|
25
|
+
| Catalogue fetch inside a component | Collection `contents` / related fields |
|
|
26
|
+
| Multiplex on `cmsLabel` / heading / `anchor` | One type = one layout (R4.2a) |
|
|
27
|
+
| RTF → plain / paragraph heuristics for layout | `RtfOrString` only |
|
|
28
|
+
| Invent / filter `links` into roles | Render links as given (unless Nick asks) |
|
|
29
|
+
| Hardcoded visitor copy, live URLs, CDN/media fallbacks | Fix CMS / import |
|
|
30
|
+
| Webflow/FlowKit CSS dumps / page CSS islands | Tokens + Tailwind utilities |
|
|
31
|
+
| Second public URL system / custom page for `generatePage` types | One IA; type owns the prefix |
|
|
32
|
+
| Mixed `@se-studio/*` majors | Aligned bump |
|
|
33
|
+
|
|
34
|
+
## Escape hatches (narrow)
|
|
35
|
+
|
|
36
|
+
- `globals.css`: shared primitives only (keyframes, RTF element maps, true design-system utilities) — **not** per-page layout ports
|
|
37
|
+
- HtmlComponent + `customCss`: last resort when a registered type cannot express the interaction — **not** the default Webflow remake path
|
|
38
|
+
|
|
39
|
+
## Related
|
|
40
|
+
|
|
41
|
+
- `site-workflows-agent-session`, `se-marketing-sites-styling-system`, `coding-discipline`
|
|
42
|
+
- Do not load Cursor Webflow DevLink / FlowKit skills on `@se-studio` customer sites
|
|
@@ -93,6 +93,16 @@ While configurable, most projects use:
|
|
|
93
93
|
* `laptop`: ~1024px+
|
|
94
94
|
* `desktop`: ~1440px+
|
|
95
95
|
|
|
96
|
+
Desktop at 1440 is the artboard the grid is built from. It is not a `max-w-[1440px]`. The grid (`container-cols-grid` outside, `content-cols-grid` inside) is what changes at other widths.
|
|
97
|
+
|
|
98
|
+
### Sections
|
|
99
|
+
|
|
100
|
+
A marketing block is `<Section>` from `@/framework/Section`. That sets `container-cols-grid` and `section-spacing`. Do not replace it with `mx-auto max-w-[…] px-… py-16`.
|
|
101
|
+
|
|
102
|
+
Width inside the section is a column span, `max-w-cols-N`, or `max-w-cols-gap-N` (spacing tokens from `--spacing-cols-*`). Type is a `fontTable` class (`h1`, `p1`) or `sizingInformation.h1` from `getSizingInformation`. Do not write `text-[32px]`, `leading-[1.2]`, or `tracking-[…]`.
|
|
103
|
+
|
|
104
|
+
If Figma has no text style on a node, stop and name that node. Do not guess a class. If the only width in the file is the frame, use the grid.
|
|
105
|
+
|
|
96
106
|
### Layout Helpers
|
|
97
107
|
|
|
98
108
|
Common layout patterns using Tailwind grid utilities:
|
|
@@ -124,9 +134,13 @@ Wrap the `RtfOrString` component with the appropriate class:
|
|
|
124
134
|
|
|
125
135
|
## Global Styles
|
|
126
136
|
|
|
127
|
-
Project-specific global styles
|
|
137
|
+
Project-specific global styles live in `src/app/globals.css`. Prefer **Tailwind utilities and design tokens in TSX** for layout. Treat new layout selectors in `globals.css` or extra `*.css` files as **review debt** unless they are shared design-system primitives.
|
|
138
|
+
|
|
139
|
+
`globals.css` is appropriate for:
|
|
128
140
|
|
|
129
141
|
* Root variables (if any)
|
|
130
|
-
* Animation keyframes
|
|
131
|
-
*
|
|
132
|
-
*
|
|
142
|
+
* Animation keyframes / `--animate-*` tokens
|
|
143
|
+
* Rich Text Formatting element maps (`.rtf-*`)
|
|
144
|
+
* True shared design-system utilities (rare; prefer tokens)
|
|
145
|
+
|
|
146
|
+
Do **not** grow per-page Webflow ports or CSS islands for layout (see `se-marketing-sites-customer-simplicity`). HtmlComponent `customCss` is a last-resort escape hatch for one-offs, not the default remake path.
|
|
@@ -231,9 +231,26 @@ When editing Contentful in parallel on the same space, use distinct cms-edit ses
|
|
|
231
231
|
- **Do not** edit `se-core-product` unless placement is `core` and user approves mode switch
|
|
232
232
|
- Consume `@se-studio/*` from npm — not monorepo workspace links
|
|
233
233
|
|
|
234
|
+
### Do not port Webflow / HTML pages
|
|
235
|
+
|
|
236
|
+
Rebuild remakes as **CMS components and collections** on core handlers (`generatePage`, registrations, `RtfOrString`, Tailwind tokens). Never “match this Webflow section in one file,” dump FlowKit/`fk-*` CSS, multiplex on `cmsLabel`/heading, flatten RTF for layout, invent link roles, or hardcode live copy/URLs. **Fail closed** when CMS is empty — omit UI or fix CMS; do not invent from the live site.
|
|
237
|
+
|
|
238
|
+
Load skill **`se-marketing-sites-customer-simplicity`** on any Webflow/HTML remake, “match the live site,” or parity task. Also: `principle-subtract-before-you-add`. Canonical rules: `docs/PHILOSOPHY.md` §5a; review BLOCKERs in [`customer-code-review.md`](../../references/agent-session/customer-code-review.md).
|
|
239
|
+
|
|
240
|
+
Do **not** use Cursor Webflow DevLink / FlowKit skills on `@se-studio` customer sites (wrong stack: CSS modules / `_webflow-style.css`).
|
|
241
|
+
|
|
234
242
|
### Figma direction (new designs) + phased visual gates
|
|
235
243
|
|
|
236
|
-
**Until the user explicitly says otherwise**, when implementing UI from a Figma file or node, treat Figma as the **direction / source of truth** for structure, spacing, type, colour, radii, alignment, and control patterns. Do not “improve” or normalize away from the comps to match older site patterns. Prefer Figma MCP design context over CMS drafts or live-site memory.
|
|
244
|
+
**Until the user explicitly says otherwise**, when implementing UI from a **new** Figma file or node, treat Figma as the **direction / source of truth** for structure, spacing, type, colour, radii, alignment, and control patterns. Do not “improve” or normalize away from the comps to match older site patterns. Prefer Figma MCP design context over CMS drafts or live-site memory.
|
|
245
|
+
|
|
246
|
+
Two things in that file are not decisions. Raise them in the plan and do not write the code until there is a concrete answer:
|
|
247
|
+
|
|
248
|
+
- The frame width (1440, 1920, whatever the artboard is) is one canvas size. The grid is how that frame adapts at other widths. It is not `max-w-[1440px]`. If the comp really seems to need a hard cap at the frame width, say so and wait.
|
|
249
|
+
- Type with no text style (`leading-[1.2]`, raw `text-[32px]`) means the designer did not specify the font. Name the node. Do not copy the leading and do not guess a `fontTable` class (`h1`, `p1`, `sizingInformation.*`).
|
|
250
|
+
|
|
251
|
+
Implement what Figma did specify with `<Section>`, `content-cols-grid`, column spans or `max-w-cols-N` / `max-w-cols-gap-N`, and a font-table class. Do not paste arbitrary classes from Figma MCP.
|
|
252
|
+
|
|
253
|
+
**Remakes from live Webflow/HTML are different:** Figma SoT does **not** apply. Use CMS structure + design tokens; do not chase pixel CSS dumps from the old site. See **Do not port Webflow / HTML pages** above.
|
|
237
254
|
|
|
238
255
|
**Do not** chase pixel-perfect polish before the **early visual gate**. Iterate with Nick on a Vercel preview first.
|
|
239
256
|
|
|
@@ -259,7 +276,7 @@ Flag layout blowouts, overflow, sparse/stretched heroes, broken grids, and type
|
|
|
259
276
|
|
|
260
277
|
Non-UI changes skip visual phases and go to code review.
|
|
261
278
|
|
|
262
|
-
**Related skills:** `site-workflows-figma-design-snapshot` / `site-workflows-apply-design-snapshot`; Figma MCP `get_design_context`.
|
|
279
|
+
**Related skills:** `se-marketing-sites-customer-simplicity` (remakes / ports); `principle-subtract-before-you-add`; `site-workflows-figma-design-snapshot` / `site-workflows-apply-design-snapshot`; Figma MCP `get_design_context`.
|
|
263
280
|
|
|
264
281
|
### Cross-project handoffs
|
|
265
282
|
|
|
@@ -247,13 +247,15 @@ Use `getSizingInformation(index)` from `@/lib/SizingInformation` for dynamic sem
|
|
|
247
247
|
| laptop | 1024px | 12 |
|
|
248
248
|
| desktop | 1440px | 12 |
|
|
249
249
|
|
|
250
|
-
|
|
250
|
+
1440 is the desktop artboard. It is not `max-w-[1440px]`. The grid is what adapts at other widths.
|
|
251
251
|
|
|
252
|
-
|
|
252
|
+
Gap and margin come from `tailwind.config.json`.
|
|
253
|
+
|
|
254
|
+
A marketing block is `<Section>` (`container-cols-grid` + `section-spacing`) with an inner `content-cols-grid`. Width is `col-span-*`, `max-w-cols-N`, or `max-w-cols-gap-N`. Type is a `fontTable` class. Do not use `py-16` as section padding, or `leading-[…]` / `text-[32px]` when the file has no text style — stop and ask which style.
|
|
253
255
|
|
|
254
256
|
## Section Spacing
|
|
255
257
|
|
|
256
|
-
|
|
258
|
+
Vertical rhythm is `section-spacing` on `<Section>`, not a hand-written `py-*`.
|
|
257
259
|
|
|
258
260
|
## RTF Classes
|
|
259
261
|
|