@se-studio/skills 1.0.1

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 (34) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/package.json +25 -0
  3. package/skills/contentful-cms-alt-text-audit/SKILL.md +60 -0
  4. package/skills/contentful-cms-cms-guidelines/README.md +166 -0
  5. package/skills/contentful-cms-cms-guidelines/colour-hint-prompt.md +77 -0
  6. package/skills/contentful-cms-cms-guidelines/evaluation-prompt.md +84 -0
  7. package/skills/contentful-cms-cms-guidelines/generate-component-guidelines.md +126 -0
  8. package/skills/contentful-cms-cms-guidelines/generation-prompt.md +231 -0
  9. package/skills/contentful-cms-cms-guidelines/html-component-authoring.md +401 -0
  10. package/skills/contentful-cms-cms-guidelines/validation-prompt.md +170 -0
  11. package/skills/contentful-cms-cms-guidelines/variant-loop.md +189 -0
  12. package/skills/contentful-cms-cms-guidelines/variant-proposal-prompt.md +131 -0
  13. package/skills/contentful-cms-core/SKILL.md +793 -0
  14. package/skills/contentful-cms-generate-all-guidelines/SKILL.md +313 -0
  15. package/skills/contentful-cms-generate-cms-guidelines/SKILL.md +313 -0
  16. package/skills/contentful-cms-image-guide/SKILL.md +240 -0
  17. package/skills/contentful-cms-navigation/SKILL.md +23 -0
  18. package/skills/contentful-cms-rich-text/SKILL.md +96 -0
  19. package/skills/contentful-cms-schema-org/SKILL.md +74 -0
  20. package/skills/contentful-cms-screenshots/SKILL.md +46 -0
  21. package/skills/contentful-cms-seo-descriptions/SKILL.md +54 -0
  22. package/skills/contentful-cms-templates/SKILL.md +21 -0
  23. package/skills/contentful-cms-update-cms-guidelines/SKILL.md +348 -0
  24. package/skills/performance-audit/SKILL.md +344 -0
  25. package/skills/se-marketing-sites-cms-routes-and-appshared/SKILL.md +99 -0
  26. package/skills/se-marketing-sites-create-collection/SKILL.md +295 -0
  27. package/skills/se-marketing-sites-create-component/SKILL.md +250 -0
  28. package/skills/se-marketing-sites-create-page/SKILL.md +183 -0
  29. package/skills/se-marketing-sites-curate-showcase-mocks/SKILL.md +344 -0
  30. package/skills/se-marketing-sites-handling-media/SKILL.md +195 -0
  31. package/skills/se-marketing-sites-lib-cms-structure/SKILL.md +83 -0
  32. package/skills/se-marketing-sites-register-cms-features/SKILL.md +95 -0
  33. package/skills/se-marketing-sites-styling-system/SKILL.md +122 -0
  34. package/skills/site-workflows-brand-context-builder/SKILL.md +98 -0
@@ -0,0 +1,195 @@
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
+ ```
@@ -0,0 +1,83 @@
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
@@ -0,0 +1,95 @@
1
+ ---
2
+ name: register-cms-features
3
+ description: Guide for registering new components, collections, and external integrations in the CMS configuration (src/lib/registrations.ts).
4
+ license: Private
5
+ metadata:
6
+ author: se-core-product
7
+ version: "1.0.0"
8
+ ---
9
+
10
+ # Registering CMS Features
11
+
12
+ The file `src/lib/registrations.ts` is where you add new components, collections, and external components. It exports three **arrays** (not Records): `componentRegistrationsList`, `collectionRegistrationsList`, `externalComponentRegistrationsList`. The **name is defined only in each registration** (in the `defineComponent` / `defineCollection` / `defineExternalComponent` call). The `cms.ts` module imports these arrays, uses `buildComponentRecord` / `buildCollectionRecord` / `buildExternalRecord` to build Records keyed by `name` (with exhaustiveness checks), then passes those Records to the core-ui build*Maps helpers. Add new registrations to the appropriate *List array in `registrations.ts`.
13
+
14
+ ## How Registration Works
15
+
16
+ The system uses registration objects created via `defineComponent`, `defineCollection`, or `defineExternalComponent` (from `@/lib/define-cms`). Each object contains:
17
+ 1. **Name**: Matches the Contentful content type ID exactly. Defined **once** in the registration (not as a Record key).
18
+ 2. **Renderer**: The React component to render.
19
+ 3. **Used Fields**: Which fields from the content model are used.
20
+ 4. **Mock Data**: Sample data for the styleguide/showcase.
21
+
22
+ ## Registering a New Component
23
+
24
+ 1. **Import the Registration**:
25
+ At the top of `src/lib/registrations.ts`, import your component's registration export.
26
+
27
+ ```typescript
28
+ import { MyNewComponentRegistration } from '@/project/components/MyNewComponent';
29
+ ```
30
+
31
+ 2. **Add to `componentRegistrationsList`**:
32
+ Find the `componentRegistrationsList` array in `registrations.ts` and add your component.
33
+
34
+ ```typescript
35
+ export const componentRegistrationsList = [
36
+ HeroRegistration,
37
+ // ...
38
+ MyNewComponentRegistration, // Add this
39
+ ] as const;
40
+ ```
41
+
42
+ *Order does not matter for functionality, but logical grouping is helpful. Missing a CMS type causes a type error in `cms.ts` when `buildComponentRecord(componentRegistrationsList)` is called.*
43
+
44
+ ## Registering a New Collection
45
+
46
+ 1. **Import the Registration** in `src/lib/registrations.ts`:
47
+
48
+ ```typescript
49
+ import { MyCollectionRegistration } from '@/project/collections/MyCollection';
50
+ ```
51
+
52
+ 2. **Add to `collectionRegistrationsList`** in `registrations.ts`:
53
+
54
+ ```typescript
55
+ export const collectionRegistrationsList = [
56
+ CardGridRegistration,
57
+ // ...
58
+ MyCollectionRegistration, // Add this
59
+ ] as const;
60
+ ```
61
+
62
+ ## Adding External Components
63
+
64
+ External components (like 3rd party forms or iframes) use a separate list in `src/lib/registrations.ts`.
65
+
66
+ 1. **Import**:
67
+ ```typescript
68
+ import { MyExternalWidgetRegistration } from '@/project/externalComponents/MyExternalWidget';
69
+ ```
70
+
71
+ 2. **Add to `externalComponentRegistrationsList`** in `registrations.ts`:
72
+ ```typescript
73
+ export const externalComponentRegistrationsList = [
74
+ ExternalIFrameRegistration,
75
+ MyExternalWidgetRegistration,
76
+ ] as const;
77
+ ```
78
+
79
+ ## Extending Type Definitions
80
+
81
+ If you introduce new Color names, Button variants, or other enumerations, update the type definitions in `src/lib/cms.ts` (types are defined there; registrations live in `registrations.ts`):
82
+
83
+ ```typescript
84
+ export type CmsColourName = NonNullable<TypeComponentFields['backgroundColour']>['values'];
85
+ // Add or modify if types are not automatically generated from Contentful
86
+ ```
87
+
88
+ **Note**: Most types are generated automatically into `@/generated/types` by the `type-gen` script. You typically don't need to manually edit types unless you are defining project-specific overrides.
89
+
90
+ ## The Showcase
91
+
92
+ Registering a component automatically adds it to the CMS Showcase (usually available at `/cms/showcase` in development). This allows you to view the component in isolation using its mock data.
93
+
94
+ * Ensure your `mock` object in the registration is complete and realistic.
95
+ * The showcase helps verify that `usedFields` and `UnusedChecker` are working correctly.
@@ -0,0 +1,122 @@
1
+ ---
2
+ name: styling-system
3
+ description: Reference guide for the marketing site styling system, including typography, colors, grids, and RTF classes.
4
+ license: Private
5
+ metadata:
6
+ author: se-core-product
7
+ version: "1.1.0"
8
+ ---
9
+
10
+ # Styling System
11
+
12
+ This project uses a customized Tailwind CSS setup where the configuration is driven by `tailwind.config.json` in each app. This JSON file acts as the source of truth for design tokens, including colors, typography, spacing, and breakpoints.
13
+
14
+ ## Configuration Source
15
+
16
+ The `tailwind.config.json` file in your app's root directory defines the following:
17
+
18
+ * **`colorOptions`**: Defines the project's color palette.
19
+ * **`fontTable`**: Defines typography styles, responsive scaling, and font families.
20
+ * **`sizes`**: Defines breakpoints, grid columns, gaps, and margins.
21
+
22
+ These configurations are processed by the build system to generate utility classes and TypeScript helpers.
23
+
24
+ ## Typography
25
+
26
+ Typography utility classes (e.g., `h1`, `h2`, `p1`, `p2`) are automatically generated from the `fontTable` in `tailwind.config.json`.
27
+
28
+ ### generated Utilities
29
+
30
+ Classes are generated for each key in `fontTable.styles`. Common keys include:
31
+
32
+ * **Headings**: `h1`, `h2`, `h3`, `h4`, `h5`, `h6`
33
+ * **Body**: `p1`, `p2`, `p3`, `p4`
34
+ * **Special**: `quote`, `button`, `nav`, etc. (varies by project)
35
+
36
+ Styles are responsive and scale automatically based on the breakpoints defined in the config (e.g., `laptop`, `desktop`).
37
+
38
+ ### Best Practice: Dynamic Sizing
39
+
40
+ Use `getSizingInformation(index)` from `@/lib/SizingInformation` to get **Element** (or **ChildElement** for items inside a collection) and typography classes. Use **Element** for the single main heading of the block; apply a class from `sizingInformation` (e.g. `sizingInformation.h1`). **preHeading** and **postHeading** must be rendered as **&lt;p&gt;** with typography classes (e.g. `sizingInformation.p`), not as heading elements.
41
+
42
+ ```typescript
43
+ import { getSizingInformation } from '@/lib/SizingInformation';
44
+
45
+ // Example usage in a component renderer
46
+ const { Element, sizingInformation } = getSizingInformation(index);
47
+ <Element className={sizingInformation.h1}>{title}</Element>
48
+ ```
49
+
50
+ For embedded content (e.g. inside rich text), pass `embedded: true` as the second argument.
51
+
52
+ ## Colors
53
+
54
+ Colors are defined in `colorOptions` within `tailwind.config.json`. The build system generates TypeScript helpers in `@/generated/colors` to access these colors safely.
55
+
56
+ ### Helper Functions
57
+
58
+ 1. **`lookupColourString(colorName, property)`**:
59
+ Get a single class for a specific property.
60
+ ```typescript
61
+ // Returns "text-primary-blue" (if 'Primary Blue' exists in config)
62
+ lookupColourString('Primary Blue', 'text')
63
+ // Returns "bg-light-gray" (if 'Light Gray' exists in config)
64
+ lookupColourString('Light Gray', 'bg')
65
+ ```
66
+
67
+ 2. **`lookupColourClassNames(bgColor, textColor)`**:
68
+ Get background AND text classes, handling automatic contrast if text color is omitted (based on `colorOpposites` in config).
69
+ ```typescript
70
+ // Returns "bg-primary-blue text-white" (if White is opposite of Primary Blue)
71
+ lookupColourClassNames('Primary Blue')
72
+ ```
73
+
74
+ ## Grid System
75
+
76
+ The grid system is defined in the `sizes` object of `tailwind.config.json`. It specifies the number of columns, margins, and gaps for each breakpoint.
77
+
78
+ ### Standard Breakpoints
79
+
80
+ While configurable, most projects use:
81
+ * `mobile`: Default (0px+)
82
+ * `tablet`: ~768px+
83
+ * `laptop`: ~1024px+
84
+ * `desktop`: ~1440px+
85
+
86
+ ### Layout Helpers
87
+
88
+ Common layout patterns using Tailwind grid utilities:
89
+
90
+ * **Full Width**: `col-span-full`
91
+ * **Centered Content**: `col-span-full laptop:col-start-2 laptop:col-span-10` (assuming 12 columns on laptop)
92
+ * **Split 50/50**:
93
+ * Left: `col-span-full laptop:col-span-6`
94
+ * Right: `col-span-full laptop:col-span-6`
95
+
96
+ ## Rich Text (RTF) Classes
97
+
98
+ Rich text styling is handled via custom utility classes defined in `src/app/globals.css`. These classes map raw HTML elements (from the CMS rich text field) to the project's typography utilities.
99
+
100
+ Common conventions for RTF classes (check your specific `globals.css`):
101
+
102
+ * **`.rtf-standard` / `.content-rich-text`**: Default styling for body content.
103
+ * **`.rtf-legal`**: Styling for terms and conditions (often smaller text, decimal lists).
104
+ * **`.rtf-article`**: Editorial styling (often larger text, specific spacing).
105
+ * **`.rtf-core`**: Minimal styling reset.
106
+
107
+ **Usage**:
108
+ Wrap the `RtfOrString` component with the appropriate class:
109
+ ```tsx
110
+ <div className="rtf-standard">
111
+ <RtfOrString data={richTextData} />
112
+ </div>
113
+ ```
114
+
115
+ ## Global Styles
116
+
117
+ Project-specific global styles, animations, and custom utility classes are located in `src/app/globals.css`. This file imports the generated Tailwind CSS and defines:
118
+
119
+ * Root variables (if any)
120
+ * Animation keyframes
121
+ * Custom component classes (e.g., `.btn-primary`)
122
+ * Rich Text Formatting classes
@@ -0,0 +1,98 @@
1
+ ---
2
+ name: "Brand Context Builder"
3
+ description: "Interactively create or update a brand context skill for a customer's site by analysing their content and asking refinement questions."
4
+ ---
5
+
6
+ # Brand Context Builder
7
+
8
+ Create a brand context skill for a customer's website. This skill guides you through analysing the site, proposing a brand context, and refining it with the user.
9
+
10
+ ## When to Use
11
+
12
+ - User wants to set up brand context for a new customer
13
+ - User says "create brand context for [site]" or "set up [customer] brand context"
14
+ - User wants to update an existing brand context
15
+
16
+ ## Workflow
17
+
18
+ ### Step 1: Gather Information
19
+
20
+ Ask the user for:
21
+ - **Site URL** (required) — e.g., "https://www.hopskipdrive.com"
22
+ - **Customer name** (optional) — e.g., "HopSkipDrive" (can be inferred)
23
+
24
+ ### Step 2: Analyse the Site
25
+
26
+ Call the `build_brand_context` tool with the site URL and customer name. This fetches the homepage and common pages via markdown routes and returns the content for analysis.
27
+
28
+ If the tool returns no content, the site may not have markdown routes enabled. Ask the user if they can provide the site URL with markdown routes, or proceed with what they can tell you about the brand.
29
+
30
+ ### Step 3: Propose Brand Context
31
+
32
+ Based on the site content returned by the tool, propose a complete brand context covering:
33
+
34
+ 1. **Customer name** — the brand name as they write it
35
+ 2. **Brand voice** — analyse the writing style (formal? casual? technical? warm?)
36
+ 3. **Target audience** — who is the site for? What are their needs?
37
+ 4. **Terminology** — brand-specific terms that should be used instead of generic words
38
+ 5. **Tone** — one-line description
39
+ 6. **SEO focus** — primary topics and keywords
40
+ 7. **Image context** — brand colours, common visual subjects and what they represent
41
+
42
+ Present the proposed context as JSON to the user.
43
+
44
+ ### Step 4: Refine
45
+
46
+ Ask the user these questions to refine the context:
47
+
48
+ 1. "Is the brand voice description accurate? Any adjustments?"
49
+ 2. "Are there brand-specific terms I missed? For example, do you have special names for your products, roles, or services?"
50
+ 3. "Are there visual elements in your imagery I should know about? (e.g., 'people in orange shirts are CareDrivers')"
51
+ 4. "Is the target audience description correct?"
52
+ 5. "Any SEO keywords or topics to add?"
53
+
54
+ Incorporate their feedback into the context.
55
+
56
+ ### Step 5: Generate the Brand Context Skill
57
+
58
+ Once the user is happy with the context, generate a brand context skill file:
59
+
60
+ ```markdown
61
+ ---
62
+ name: "[CustomerName] Brand Context"
63
+ description: "Brand voice, terminology, audience, and visual guidelines for [CustomerName] ([siteUrl])."
64
+ ---
65
+
66
+ # Brand Context: [CustomerName]
67
+ **Site:** [siteUrl]
68
+ **Brand voice:** [brandVoice]
69
+ **Target audience:** [targetAudience]
70
+ **Tone:** [tone]
71
+ **SEO focus:** [seoFocus]
72
+
73
+ ## Terminology
74
+ Use these brand-specific terms instead of generic alternatives:
75
+ - **[term]**: [meaning]
76
+ ...
77
+
78
+ ## Image Interpretation
79
+ **Brand colours:** [colours]
80
+ **When you see → interpret as:**
81
+ - "[visual]" → [meaning]
82
+ ...
83
+ ```
84
+
85
+ ### Step 6: Save
86
+
87
+ Tell the user:
88
+
89
+ 1. **For Claude Desktop:** Save the skill content as `Skill.md` in a folder named `[customer-name]-brand-context/`, ZIP it, and upload via Customize > Skills
90
+ 2. **For the project:** Save the JSON as `.site-context.json` in the project root, then run `generate-skills` to create the skill automatically
91
+ 3. **To update later:** Edit `.site-context.json` and re-run `generate-skills`, or use this skill again to rebuild from scratch
92
+
93
+ ## Tips
94
+
95
+ - If the site has a blog, look at article content for more terminology and voice clues
96
+ - Company about pages are great for understanding target audience
97
+ - Service/product pages reveal the key terms and benefits language
98
+ - Look for consistent phrases that appear across multiple pages — those are likely intentional brand language