@se-studio/skills 1.0.5 → 1.0.11
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 +38 -0
- package/package.json +1 -1
- package/skills/contentful-cms-setup/SKILL.md +91 -0
- package/skills/site-workflows-apply-design-snapshot/SKILL.md +285 -0
- package/skills/site-workflows-contentful-vercel-setup/SKILL.md +300 -0
- package/skills/site-workflows-copy-doc-snapshot/SKILL.md +222 -0
- package/skills/site-workflows-figma-design-snapshot/SKILL.md +390 -0
- package/skills/site-workflows-new-project/SKILL.md +278 -0
- package/skills/site-workflows-project-cleanup/SKILL.md +362 -0
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: site-workflows-project-cleanup
|
|
3
|
+
description: Strip an existing SE Studio Next.js/Contentful project to a bare-bones baseline — black/white color system, system font, only Generic Component, Generic Collection, and Related Articles Collection registered, with minimal navigation and footer stubs. Run this when you need to clean a customer project down to a reusable template.
|
|
4
|
+
license: MIT
|
|
5
|
+
metadata:
|
|
6
|
+
author: se-studio
|
|
7
|
+
version: "1.0.0"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# SE Project Cleanup
|
|
11
|
+
|
|
12
|
+
Strips an existing SE Studio project to a bare-bones baseline. After this skill runs you will have:
|
|
13
|
+
- **Colors**: White (`Light`) and Black (`Dark`) only
|
|
14
|
+
- **Font**: system-ui (no custom or Google fonts)
|
|
15
|
+
- **Components**: Generic Component only
|
|
16
|
+
- **Collections**: Generic Collection + Related Articles Collection
|
|
17
|
+
- **Nav/Footer**: Minimal HTML stubs
|
|
18
|
+
- **Contentful schema**: `componentType` and `collectionType` enums trimmed to match
|
|
19
|
+
|
|
20
|
+
Run `pnpm validate` at the end to confirm a clean TypeScript build.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Step 1 — Update `tailwind.config.json`
|
|
25
|
+
|
|
26
|
+
Replace `colorOptions` with black and white only, update font family, and remove OpenType feature settings:
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"colorOptions": {
|
|
31
|
+
"Light": "#FFFFFF",
|
|
32
|
+
"Dark": "#000000"
|
|
33
|
+
},
|
|
34
|
+
"colorFile": "./colors.ts",
|
|
35
|
+
"foregroundColors": ["Dark", "Light"],
|
|
36
|
+
"colorOpposites": {
|
|
37
|
+
"Light": "Dark",
|
|
38
|
+
"Dark": "Light"
|
|
39
|
+
},
|
|
40
|
+
"sizes": { /* keep existing sizes unchanged */ },
|
|
41
|
+
"fontTable": {
|
|
42
|
+
"font": "system-ui",
|
|
43
|
+
"weight": 400,
|
|
44
|
+
"lineHeight": 1.2,
|
|
45
|
+
"styles": { /* see below */ }
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
In `fontTable.styles`:
|
|
51
|
+
- Remove the top-level `"additional"` block (which has `font-feature-settings`)
|
|
52
|
+
- For every style that has an `"additional"` block containing `font-feature-settings`, remove that `additional` block entirely
|
|
53
|
+
- Keep any `"additional"` blocks that contain only `text-transform` (those are still valid with system fonts)
|
|
54
|
+
- Keep all size values, weight overrides, lineHeight, and letterSpacing values unchanged
|
|
55
|
+
|
|
56
|
+
After this change the font table will reference `system-ui` but retain all the responsive size scales.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Step 2 — Update `src/project/font.ts`
|
|
61
|
+
|
|
62
|
+
Delete the entire file. It exports `noiVariableFlex` (local font) and `ibmPlexMono` (Google font) — both unused after cleanup.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Step 3 — Update `src/app/layout.tsx`
|
|
67
|
+
|
|
68
|
+
1. Remove the import line: `import { ibmPlexMono, noiVariableFlex } from '@/project/font';`
|
|
69
|
+
2. In the `html` element's `className`, remove `noiVariableFlex.variable` and `ibmPlexMono.variable`
|
|
70
|
+
|
|
71
|
+
The html element should look like:
|
|
72
|
+
```tsx
|
|
73
|
+
<html
|
|
74
|
+
lang="en"
|
|
75
|
+
suppressHydrationWarning
|
|
76
|
+
className={cn(
|
|
77
|
+
'antialiased',
|
|
78
|
+
process.env.DEBUG_TAILWIND === 'true' && 'debug-screens',
|
|
79
|
+
process.env.SHOW_SECTION_OUTLINE === 'true' && 'show-section-outline',
|
|
80
|
+
)}
|
|
81
|
+
>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Step 4 — Update `src/app/globals.css`
|
|
87
|
+
|
|
88
|
+
### In the `@theme` block, make these changes:
|
|
89
|
+
|
|
90
|
+
**Replace** the `--font-sans` and `--font-serif` lines with:
|
|
91
|
+
```css
|
|
92
|
+
--font-sans: system-ui, ui-sans-serif, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
|
93
|
+
--font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**Remove** all `--animate-*` custom properties:
|
|
97
|
+
```
|
|
98
|
+
--animate-cardRotate
|
|
99
|
+
--animate-linkRotate
|
|
100
|
+
--animate-ticker
|
|
101
|
+
--animate-fadeInGrow
|
|
102
|
+
--animate-shapeShiftClip
|
|
103
|
+
--animate-shapeShiftSpin
|
|
104
|
+
--animate-clipReveal
|
|
105
|
+
--animate-filmGrainShift
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Remove these `@utility` blocks entirely:
|
|
109
|
+
- `animate-ticker`
|
|
110
|
+
- `animate-fade-in-grow`
|
|
111
|
+
- `animate-shape-shift`
|
|
112
|
+
- `animate-card-rotate`
|
|
113
|
+
- `animate-clip-reveal`
|
|
114
|
+
- `film-grain`
|
|
115
|
+
- `image-item-h` (ArticleBrowser-specific)
|
|
116
|
+
- `visual-cols` (VisualsCollection-specific)
|
|
117
|
+
- `visual-width` (VisualsCollection-specific)
|
|
118
|
+
|
|
119
|
+
### Remove all `@keyframes` blocks:
|
|
120
|
+
- `cardRotate`
|
|
121
|
+
- `linkRotate`
|
|
122
|
+
- `ticker`
|
|
123
|
+
- `growFade`
|
|
124
|
+
- `shapeShiftClip`
|
|
125
|
+
- `shapeShiftSpin`
|
|
126
|
+
- `clipReveal`
|
|
127
|
+
- `filmGrainShift`
|
|
128
|
+
|
|
129
|
+
### Remove the view transition media query block:
|
|
130
|
+
```css
|
|
131
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
132
|
+
::view-transition-group(*) { ... }
|
|
133
|
+
::view-transition-old(root) { ... }
|
|
134
|
+
::view-transition-new(root) { ... }
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### In the RTF classes, replace `bg-yellow/20` with `bg-dark/10`:
|
|
139
|
+
Three occurrences — in `.rtf-standard > blockquote`, `.rtf-article > blockquote`, and `.rtf-legal > blockquote`.
|
|
140
|
+
|
|
141
|
+
### Remove the dead-code block at the bottom:
|
|
142
|
+
```css
|
|
143
|
+
.dark-component .standard-rtf { ... }
|
|
144
|
+
.light-component .standard-rtf { ... }
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Remove the Orejime scroll-lock workaround if not using Orejime consent:
|
|
148
|
+
The block starting with `.orejimeHtml-WithModalOpen.orejimeHtml-WithModalOpen body { ... }` — remove if the project does not use the Orejime consent banner.
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Step 5 — Update `src/lib/registrations.ts`
|
|
153
|
+
|
|
154
|
+
Keep only these three registrations:
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
import { GenericComponentRegistration } from '@/project/components/TemplateComponent';
|
|
158
|
+
import { GenericCollectionRegistration } from '@/project/collections/TemplateCollection';
|
|
159
|
+
import { RelatedArticlesCollectionRegistration } from '@/project/collections/RelatedArticlesCollection';
|
|
160
|
+
|
|
161
|
+
export const componentRegistrationsList = [
|
|
162
|
+
GenericComponentRegistration,
|
|
163
|
+
] as const;
|
|
164
|
+
|
|
165
|
+
export const collectionRegistrationsList = [
|
|
166
|
+
GenericCollectionRegistration,
|
|
167
|
+
RelatedArticlesCollectionRegistration,
|
|
168
|
+
] as const;
|
|
169
|
+
|
|
170
|
+
export const externalComponentRegistrationsList = [] as const;
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Remove all other imports and registrations.
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Step 6 — Delete component files
|
|
178
|
+
|
|
179
|
+
Delete these files from `src/project/components/`:
|
|
180
|
+
- `ArticleDescription.tsx`
|
|
181
|
+
- `ArticleHero.tsx`
|
|
182
|
+
- `ArticleRichText.tsx`
|
|
183
|
+
- `Quote.tsx`
|
|
184
|
+
- `SimpleParagraph.tsx`
|
|
185
|
+
- `TwoColumnRichText.tsx`
|
|
186
|
+
- `ViewTransitionTrackedLink.tsx`
|
|
187
|
+
|
|
188
|
+
Also delete these files from `src/project/components/Navigation/`:
|
|
189
|
+
- `NavMenu.tsx`
|
|
190
|
+
- `MobileNav.tsx`
|
|
191
|
+
- `ContactNavItem.tsx`
|
|
192
|
+
|
|
193
|
+
Keep: `TemplateComponent.tsx`, `Navigation/index.tsx` (will be replaced in Step 8), `Navigation/types.ts`, `Footer/index.tsx` (will be replaced in Step 9), `Footer/types.ts`
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Step 7 — Delete collection files
|
|
198
|
+
|
|
199
|
+
Delete these from `src/project/collections/`:
|
|
200
|
+
- `ArticleBrowser/` (entire directory)
|
|
201
|
+
- `ProcessListCollection.tsx`
|
|
202
|
+
- `SeparatedVisualsCollection.tsx`
|
|
203
|
+
- `TeamGridCollection.tsx`
|
|
204
|
+
- `TextAndCarouselCollection.tsx`
|
|
205
|
+
- `TextAndCarouselCarousel.tsx`
|
|
206
|
+
- `VisualsCollection.tsx`
|
|
207
|
+
|
|
208
|
+
Keep: `TemplateCollection.tsx`, `LinkCard.tsx` (used internally by TemplateCollection), `RelatedArticlesCollection.tsx`
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Step 8 — Delete external component files
|
|
213
|
+
|
|
214
|
+
Delete all files in `src/project/externalComponents/` (IFrame and Pardot integrations).
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## Step 9 — Replace Navigation with minimal stub
|
|
219
|
+
|
|
220
|
+
Replace `src/project/components/Navigation/index.tsx` with:
|
|
221
|
+
|
|
222
|
+
```tsx
|
|
223
|
+
'use client';
|
|
224
|
+
import type { INavigation } from '@se-studio/core-data-types';
|
|
225
|
+
import type { NavigationProps } from './types';
|
|
226
|
+
|
|
227
|
+
export const Navigation: React.FC<NavigationProps> = ({ navigation: _navigation }) => {
|
|
228
|
+
return (
|
|
229
|
+
<header className="fixed top-0 left-0 right-0 z-50 h-[var(--nav-height)] bg-light border-b border-dark/10 flex items-center px-4">
|
|
230
|
+
<nav>
|
|
231
|
+
<span className="p2 font-semibold">Site Name</span>
|
|
232
|
+
</nav>
|
|
233
|
+
</header>
|
|
234
|
+
);
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
export default Navigation;
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Step 10 — Replace Footer with minimal stub
|
|
243
|
+
|
|
244
|
+
Replace `src/project/components/Footer/index.tsx` with:
|
|
245
|
+
|
|
246
|
+
```tsx
|
|
247
|
+
'use client';
|
|
248
|
+
import type { FooterProps } from './types';
|
|
249
|
+
|
|
250
|
+
export const Footer: React.FC<FooterProps> = ({ navigation: _navigation }) => {
|
|
251
|
+
return (
|
|
252
|
+
<footer className="bg-dark text-light py-8 px-4 text-center">
|
|
253
|
+
<p className="p3">© {new Date().getFullYear()} Site Name</p>
|
|
254
|
+
</footer>
|
|
255
|
+
);
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
export default Footer;
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Delete `src/project/components/Footer/MobileFooter.tsx` if it exists.
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## Step 11 — Clean up Contentful schema
|
|
266
|
+
|
|
267
|
+
Create `scripts/clean-schema.js` (or update it if it already exists):
|
|
268
|
+
|
|
269
|
+
```js
|
|
270
|
+
#!/usr/bin/env node
|
|
271
|
+
'use strict';
|
|
272
|
+
const fs = require('node:fs');
|
|
273
|
+
|
|
274
|
+
const inputPath = 'scripts/master-schema.json';
|
|
275
|
+
const outputPath = 'scripts/clean-schema.json';
|
|
276
|
+
|
|
277
|
+
if (!fs.existsSync(inputPath)) {
|
|
278
|
+
console.error(`Input file not found: ${inputPath}`);
|
|
279
|
+
console.error('Export the schema first: contentful space export --skip-content --content-file scripts/master-schema.json');
|
|
280
|
+
process.exit(1);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const schema = JSON.parse(fs.readFileSync(inputPath, 'utf8'));
|
|
284
|
+
|
|
285
|
+
// Trim componentType to bare-bones set
|
|
286
|
+
const component = schema.contentTypes.find(ct => ct.sys.id === 'component');
|
|
287
|
+
if (component) {
|
|
288
|
+
const field = component.fields.find(f => f.id === 'componentType');
|
|
289
|
+
if (field) {
|
|
290
|
+
field.validations = field.validations.map(v => v.in ? { in: ['Generic'] } : v);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Trim collectionType to bare-bones set
|
|
295
|
+
const collection = schema.contentTypes.find(ct => ct.sys.id === 'collection');
|
|
296
|
+
if (collection) {
|
|
297
|
+
const field = collection.fields.find(f => f.id === 'collectionType');
|
|
298
|
+
if (field) {
|
|
299
|
+
field.validations = field.validations.map(v =>
|
|
300
|
+
v.in ? { in: ['Generic', 'Related articles'] } : v
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Clear externalComponentType (no external components in bare-bones setup)
|
|
306
|
+
const ext = schema.contentTypes.find(ct => ct.sys.id === 'externalComponent');
|
|
307
|
+
if (ext) {
|
|
308
|
+
const field = ext.fields.find(f => f.id === 'externalComponentType');
|
|
309
|
+
if (field) {
|
|
310
|
+
field.validations = field.validations.map(v => v.in ? { in: [] } : v);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
fs.writeFileSync(outputPath, JSON.stringify(schema, null, 2));
|
|
315
|
+
console.log(`Clean schema written to ${outputPath}`);
|
|
316
|
+
console.log('Component types kept:', ['Generic']);
|
|
317
|
+
console.log('Collection types kept:', ['Generic', 'Related articles']);
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Run it:
|
|
321
|
+
```bash
|
|
322
|
+
node scripts/clean-schema.js
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
Then import to the target Contentful space (use the space ID from `.env.local`):
|
|
326
|
+
```bash
|
|
327
|
+
contentful space import \
|
|
328
|
+
--space-id <TARGET_SPACE_ID> \
|
|
329
|
+
--environment-id master \
|
|
330
|
+
--content-file scripts/clean-schema.json
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
> If cleaning an **existing** space (not a new one), use the Contentful Management API or UI to update the `componentType` and `collectionType` field validations directly, rather than importing. Importing to an existing space with live content can cause conflicts.
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
## Step 12 — Regenerate and validate
|
|
338
|
+
|
|
339
|
+
```bash
|
|
340
|
+
pnpm codegen
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
This regenerates `src/generated/colors.ts` (now only `Light` and `Dark`) and `src/generated/setailwind.css` (system font, updated color variables).
|
|
344
|
+
|
|
345
|
+
```bash
|
|
346
|
+
pnpm validate
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
Fix any TypeScript errors that surface from the removed imports. Common issues:
|
|
350
|
+
- References to deleted components in other files (check `src/lib/` for any direct imports)
|
|
351
|
+
- `viewTransitions.ts` may import from `ViewTransitionTrackedLink` — remove those imports
|
|
352
|
+
- Any analytics wrappers that reference removed component names
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## What is deliberately left untouched
|
|
357
|
+
|
|
358
|
+
- `src/app/(cms-routes)/` — all routing is left as-is; the CMS routes work with whatever is registered
|
|
359
|
+
- `src/lib/constants.ts` — site title/description stays as-is for cleanup; update manually for new projects
|
|
360
|
+
- `src/project/STYLING.md` and `src/project/ANIMATION.md` — left for human review; update to reflect the new bare-bones system
|
|
361
|
+
- `src/project/font.ts` — deleted (step 2 above)
|
|
362
|
+
- `scripts/master-schema.json` — never modified, always kept as the original export
|