@champpaba/claude-agent-kit 3.3.0 → 3.4.0

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.
@@ -45,47 +45,60 @@ Generate design system files:
45
45
 
46
46
  ## STEP 0: Discovery & Validation
47
47
 
48
- ```javascript
49
- // 1. Find extracted sites from design-system/extracted/*/data.yaml
50
- const extractedDirs = glob('design-system/extracted/*/data.yaml');
48
+ ### STEP 0.1: Find Extracted Site Data
51
49
 
52
- if (extractedDirs.length === 0) {
53
- return error(`
54
- No extracted data found
50
+ 1. Search for extracted site data:
51
+ ```
52
+ Glob: design-system/extracted/*/data.yaml
53
+ ```
55
54
 
56
- Please extract at least 1 site first:
57
- /extract https://motherduck.com
58
- /extract https://linear.app
55
+ **If no files found:**
56
+ ```
57
+ No extracted data found
59
58
 
60
- Then run: /designsetup @prd.md @project.md
61
- `);
62
- }
59
+ Please extract at least 1 site first:
60
+ /extract https://motherduck.com
61
+ /extract https://linear.app
63
62
 
64
- // 2. Load all extracted site data (YAML format with psychology)
65
- const extractedData = {};
66
- for (const file of extractedDirs) {
67
- const siteName = path.basename(path.dirname(file)); // Get folder name
68
- extractedData[siteName] = YAML.parse(Read(file));
69
- }
63
+ Then run: /designsetup @prd.md @project.md
64
+ ```
65
+ STOP here, do not continue
70
66
 
71
- // 4. Load context files
72
- const contextArgs = args.filter(arg => arg.startsWith('@'));
73
- const contexts = {};
67
+ **If files found:**
68
+ ```
69
+ Found extracted sites: [list site names]
70
+ ```
71
+ → Continue to STEP 0.2
74
72
 
75
- if (contextArgs.length > 0) {
76
- for (const arg of contextArgs) {
77
- const filePath = arg.substring(1); // Remove @
73
+ ### STEP 0.2: Load Extracted Site Data
78
74
 
79
- if (!exists(filePath)) {
80
- warn(`Context file not found: ${filePath} (skipping)`);
81
- continue;
82
- }
75
+ For each extracted site found:
76
+ 1. Extract the site name from the path (the folder name between `extracted/` and `/data.yaml`)
77
+ 2. Read the data.yaml file
78
+ 3. Parse the YAML content
79
+ 4. Store in memory for later use (map site name to data)
83
80
 
84
- const fileName = path.basename(filePath);
85
- contexts[fileName] = Read(filePath);
86
- }
87
- }
88
- ```
81
+ Continue to STEP 0.3
82
+
83
+ ### STEP 0.3: Load Context Files (Optional)
84
+
85
+ 1. Check if user provided context files (arguments starting with `@`)
86
+
87
+ **If no context files provided:**
88
+ - Set contexts as empty
89
+ - Will use interactive mode later
90
+ → Continue to STEP 0.4
91
+
92
+ **If context files provided:**
93
+ For each context file argument:
94
+ 1. Remove the `@` prefix to get the file path
95
+ 2. Check if file exists:
96
+ - **If not found:** Warn user and skip this file
97
+ - **If found:** Read the file content and store with filename as key
98
+
99
+ → Continue to STEP 0.4
100
+
101
+ ### STEP 0.4: Report Discovery Results
89
102
 
90
103
  **Report:**
91
104
  ```
@@ -110,19 +123,24 @@ ${Object.keys(contexts).length > 0 ? Object.keys(contexts).map(c => ` - ${c}`)
110
123
 
111
124
  ## STEP 1: Context Analysis
112
125
 
113
- ```javascript
114
- let contextAnalysis;
126
+ ### STEP 1.1: Check for Context Files
127
+
128
+ **If context files were loaded in STEP 0.3:**
129
+ → Continue to STEP 1.2 (AI Analysis)
115
130
 
116
- if (Object.keys(contexts).length > 0) {
117
- // AI analyzes context files
118
- const analysisPrompt = `
131
+ **If no context files:**
132
+ Skip to STEP 1.3 (Interactive Questions)
133
+
134
+ ### STEP 1.2: AI Analysis of Context Files
135
+
136
+ 1. Ask Claude to analyze the context files and identify project characteristics
137
+
138
+ **Analysis Prompt:**
139
+ ```
119
140
  You are analyzing project context to recommend design directions.
120
141
 
121
142
  Context Files:
122
- ${Object.entries(contexts).map(([name, content]) => `
123
- ## ${name}
124
- ${content.substring(0, 2000)} // First 2000 chars
125
- `).join('\n')}
143
+ [Include each context file name and first 2000 characters of content]
126
144
 
127
145
  Task: Identify project characteristics and return JSON.
128
146
 
@@ -146,69 +164,56 @@ Return JSON:
146
164
  }
147
165
 
148
166
  If context is insufficient or unclear, set "has_context": false.
149
- `;
167
+ ```
150
168
 
151
- contextAnalysis = await LLM({
152
- prompt: analysisPrompt,
153
- response_format: 'json'
154
- });
169
+ 2. Parse the JSON response from Claude
155
170
 
156
- } else {
157
- contextAnalysis = { has_context: false };
158
- }
171
+ **If has_context is true:**
172
+ Skip to STEP 1.4 (Report)
159
173
 
160
- // If no context, ask user
161
- if (!contextAnalysis.has_context) {
162
- const userInput = await AskUserQuestion({
163
- questions: [
164
- {
165
- question: "What type of product are you building?",
166
- header: "Product Type",
167
- multiSelect: false,
168
- options: [
169
- { label: "SaaS Dashboard", description: "Business software, data tools, analytics" },
170
- { label: "E-commerce", description: "Online store, marketplace, shopping" },
171
- { label: "Marketing Site", description: "Landing pages, content, blog" },
172
- { label: "Internal Tool", description: "Admin panels, workflows, dashboards" }
173
- ]
174
- },
175
- {
176
- question: "Who is your target audience?",
177
- header: "Audience",
178
- multiSelect: false,
179
- options: [
180
- { label: "Gen Z (18-25)", description: "Young, tech-savvy, bold preferences" },
181
- { label: "Millennials (26-40)", description: "Professional, value-driven, modern" },
182
- { label: "Enterprise (40+)", description: "Conservative, trust-focused, established" },
183
- { label: "Developers", description: "Technical, efficiency-focused, minimal" }
184
- ]
185
- },
186
- {
187
- question: "What brand personality do you want?",
188
- header: "Brand",
189
- multiSelect: true,
190
- options: [
191
- { label: "Bold", description: "Stand out, memorable, confident, different" },
192
- { label: "Professional", description: "Trustworthy, credible, serious, polished" },
193
- { label: "Playful", description: "Fun, friendly, approachable, warm" },
194
- { label: "Minimal", description: "Clean, simple, understated, elegant" }
195
- ]
196
- }
197
- ]
198
- });
199
-
200
- contextAnalysis = {
201
- has_context: true,
202
- from_user_input: true,
203
- product_type: userInput.answers["Product Type"],
204
- target_audience: {
205
- demographics: userInput.answers["Audience"],
206
- tech_savvy: userInput.answers["Audience"].includes("Gen Z") || userInput.answers["Audience"].includes("Developers") ? "high" : "medium"
207
- },
208
- brand_personality: userInput.answers["Brand"].split(',').map(s => s.trim().toLowerCase())
209
- };
210
- }
211
- ```
174
+ **If has_context is false:**
175
+ Continue to STEP 1.3 (Interactive Questions)
176
+
177
+ ### STEP 1.3: Interactive Questions (Fallback)
178
+
179
+ Ask user to answer these questions:
180
+
181
+ **Question 1: Product Type**
182
+ - Header: "Product Type"
183
+ - Single selection
184
+ - Options:
185
+ - "SaaS Dashboard" - Business software, data tools, analytics
186
+ - "E-commerce" - Online store, marketplace, shopping
187
+ - "Marketing Site" - Landing pages, content, blog
188
+ - "Internal Tool" - Admin panels, workflows, dashboards
189
+
190
+ **Question 2: Target Audience**
191
+ - Header: "Audience"
192
+ - Single selection
193
+ - Options:
194
+ - "Gen Z (18-25)" - Young, tech-savvy, bold preferences
195
+ - "Millennials (26-40)" - Professional, value-driven, modern
196
+ - "Enterprise (40+)" - Conservative, trust-focused, established
197
+ - "Developers" - Technical, efficiency-focused, minimal
198
+
199
+ **Question 3: Brand Personality**
200
+ - Header: "Brand"
201
+ - Multiple selection allowed
202
+ - Options:
203
+ - "Bold" - Stand out, memorable, confident, different
204
+ - "Professional" - Trustworthy, credible, serious, polished
205
+ - "Playful" - Fun, friendly, approachable, warm
206
+ - "Minimal" - Clean, simple, understated, elegant
207
+
208
+ Build context analysis from user answers:
209
+ - product_type: from Question 1
210
+ - target_audience.demographics: from Question 2
211
+ - target_audience.tech_savvy: "high" if Gen Z or Developers selected, otherwise "medium"
212
+ - brand_personality: list from Question 3 (converted to lowercase)
213
+
214
+ Continue to STEP 1.4
215
+
216
+ ### STEP 1.4: Report Context Analysis
212
217
 
213
218
  **Report:**
214
219
  ```
@@ -229,231 +234,197 @@ if (!contextAnalysis.has_context) {
229
234
 
230
235
  > **Key Change:** Interactive loop until user accepts 100%
231
236
 
232
- ```javascript
233
- let round = 1;
234
- let maxRounds = 3;
235
- let userAccepted = false;
236
- let selectedStyle = null;
237
- let selectedAnimations = [];
238
- let selectedTheme = null;
237
+ **Loop Configuration:**
238
+ - Maximum rounds: 3
239
+ - Current round: starts at 1
240
+ - User must accept to exit loop
239
241
 
240
- while (!userAccepted && round <= maxRounds) {
241
- output(`
242
+ ### STEP 2.1: Start New Round
243
+
244
+ Display round header:
245
+ ```
242
246
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
243
- 📋 ROUND ${round}/${maxRounds}: Style Selection
247
+ 📋 ROUND [current round]/3: Style Selection
244
248
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
245
- `);
246
-
247
- // ========== STYLE OPTIONS (VERBOSE) ==========
248
-
249
- const styleOptions = [];
250
-
251
- // Generate options from extracted data
252
- for (const [siteName, data] of Object.entries(extractedData)) {
253
- styleOptions.push({
254
- site: siteName,
255
- style: data.style.detected,
256
- confidence: data.style.confidence,
257
- characteristics: data.style.characteristics,
258
- feel: data.style.feel,
259
- colors: data.colors.primary,
260
- animations: data.animation_libraries,
261
- scrollPatterns: data.scroll_animations.patterns,
262
- decorativeTypes: data.decorative_elements.types
263
- });
264
- }
249
+ ```
250
+
251
+ Continue to STEP 2.2
252
+
253
+ ### STEP 2.2: Build Style Options from Extracted Data
254
+
255
+ For each extracted site:
256
+ 1. Extract the following information from the site's data:
257
+ - site: site name
258
+ - style: data.style.detected
259
+ - confidence: data.style.confidence
260
+ - characteristics: data.style.characteristics
261
+ - feel: data.style.feel
262
+ - colors: data.colors.primary
263
+ - animations: data.animation_libraries
264
+ - scrollPatterns: data.scroll_animations.patterns
265
+ - decorativeTypes: data.decorative_elements.types
266
+ 2. Add to options list
267
+
268
+ → Continue to STEP 2.3
269
+
270
+ ### STEP 2.3: Calculate Match Scores
271
+
272
+ For each style option:
273
+ 1. Start with base score = confidence value
274
+ 2. Apply brand personality bonuses:
275
+ - **If brand includes "bold":**
276
+ - Add +15 if style is "Neo-Brutalism" or "Playful/Creative"
277
+ - **If brand includes "professional":**
278
+ - Add +15 if style is "Minimalist" or "Modern SaaS"
279
+ - **If brand includes "playful":**
280
+ - Add +15 if style is "Playful/Creative"
281
+ - **If brand includes "minimal":**
282
+ - Add +15 if style is "Minimalist"
283
+ 3. Cap final score at 100 (max)
284
+ 4. Store as matchScore
265
285
 
266
- // Calculate match scores based on context
267
- const scoredOptions = styleOptions.map(opt => {
268
- let score = opt.confidence;
269
-
270
- // Bonus for matching brand personality
271
- if (contextAnalysis.brand_personality) {
272
- if (contextAnalysis.brand_personality.includes('bold') &&
273
- (opt.style === 'Neo-Brutalism' || opt.style === 'Playful/Creative')) {
274
- score += 15;
275
- }
276
- if (contextAnalysis.brand_personality.includes('professional') &&
277
- (opt.style === 'Minimalist' || opt.style === 'Modern SaaS')) {
278
- score += 15;
279
- }
280
- if (contextAnalysis.brand_personality.includes('playful') &&
281
- opt.style === 'Playful/Creative') {
282
- score += 15;
283
- }
284
- if (contextAnalysis.brand_personality.includes('minimal') &&
285
- opt.style === 'Minimalist') {
286
- score += 15;
287
- }
288
- }
289
-
290
- return { ...opt, matchScore: Math.min(score, 100) };
291
- }).sort((a, b) => b.matchScore - a.matchScore);
292
-
293
- // Display verbose options
294
- for (const [index, option] of scoredOptions.entries()) {
295
- const letter = String.fromCharCode(65 + index);
296
- const isRecommended = index === 0;
297
-
298
- output(`
286
+ Sort all options by matchScore (highest first)
287
+
288
+ Continue to STEP 2.4
289
+
290
+ ### STEP 2.4: Display Verbose Style Options
291
+
292
+ For each scored option (in sorted order):
293
+ 1. Assign a letter (A, B, C, etc.)
294
+ 2. Mark the first option (highest score) as "RECOMMENDED"
295
+ 3. Display in this format:
296
+
297
+ ```
299
298
  ┌─────────────────────────────────────────────────────────────┐
300
- │ Option ${letter}: ${option.style} ${isRecommended ? '⭐ RECOMMENDED' : ''}
301
- │ Source: ${option.site}
302
- │ Match Score: ${option.matchScore}%
299
+ │ Option [Letter]: [Style Name] [⭐ RECOMMENDED if first]
300
+ │ Source: [site name]
301
+ │ Match Score: [score]%
303
302
  ├─────────────────────────────────────────────────────────────┤
304
303
 
305
304
  │ 📝 Characteristics:
306
- ${option.characteristics.map(c => ` ${c}`).join('\n│ ')}
305
+ [characteristic 1]
306
+ │ • [characteristic 2]
307
+ │ ...
307
308
 
308
- │ 🎭 Feel: ${option.feel}
309
+ │ 🎭 Feel: [feel description]
309
310
 
310
- │ 🎨 Colors: ${option.colors.join(', ')}
311
+ │ 🎨 Colors: [primary colors list]
311
312
 
312
313
  │ 🎬 Animations Available:
313
- ${option.animations.length > 0 ? option.animations.map(a => ` ${a.name}`).join('\n│ ') : ' (none detected)'}
314
+ [animation 1]
315
+ │ • [animation 2]
316
+ │ (or "(none detected)")
314
317
 
315
318
  │ 📜 Scroll Patterns:
316
- ${option.scrollPatterns.length > 0 ? option.scrollPatterns.map(p => ` ${p}`).join('\n│ ') : ' (none detected)'}
319
+ [pattern 1]
320
+ │ • [pattern 2]
321
+ │ (or "(none detected)")
317
322
 
318
323
  │ 🖼️ Decorative Elements:
319
- ${option.decorativeTypes.length > 0 ? option.decorativeTypes.map(d => ` ${d}`).join('\n│ ') : ' (none detected)'}
324
+ [element 1]
325
+ │ • [element 2]
326
+ │ (or "(none detected)")
320
327
 
321
328
  └─────────────────────────────────────────────────────────────┘
322
- `);
323
- }
329
+ ```
324
330
 
325
- // Ask user to select or provide feedback
326
- const styleChoice = await AskUserQuestion({
327
- questions: [{
328
- question: "เลือก style ที่ชอบ หรือพิมพ์ feedback:",
329
- header: "Style",
330
- multiSelect: false,
331
- options: [
332
- ...scoredOptions.map((opt, i) => ({
333
- label: `${String.fromCharCode(65 + i)}: ${opt.style}`,
334
- description: `${opt.matchScore}% match - ${opt.feel}`
335
- })),
336
- { label: "Mix/Custom", description: "ผสมหลาย style หรือปรับแต่งเอง" }
337
- ]
338
- }]
339
- });
340
-
341
- if (styleChoice.answers["Style"] === "Mix/Custom") {
342
- output(`
343
- พิมพ์ความต้องการ (ตัวอย่าง: "ชอบ border ของ A แต่อยากได้สี soft กว่านี้"):
344
- `);
345
- const customInput = await getUserTextInput();
346
-
347
- // AI interprets and adjusts
348
- output(`
349
- 🤖 กำลังปรับตาม feedback: "${customInput}"...
350
- `);
351
-
352
- round++;
353
- continue; // Loop again with adjusted options
354
- }
331
+ Continue to STEP 2.5
332
+
333
+ ### STEP 2.5: Ask User to Select Style
334
+
335
+ Ask user to choose:
336
+ - Header: "Style"
337
+ - Single selection
338
+ - Options:
339
+ - For each scored option: "[Letter]: [Style Name]" - "[Score]% match - [Feel]"
340
+ - Last option: "Mix/Custom" - "ผสมหลาย style หรือปรับแต่งเอง"
341
+
342
+ **If user selects "Mix/Custom":**
343
+ 1. Display prompt: "พิมพ์ความต้องการ (ตัวอย่าง: 'ชอบ border ของ A แต่อยากได้สี soft กว่านี้'):"
344
+ 2. Get text input from user
345
+ 3. Display: "🤖 กำลังปรับตาม feedback: '[input]'..."
346
+ 4. Increment round counter
347
+ 5. **If round <= 3:** → Go back to STEP 2.1 (new round with adjusted options)
348
+ 6. **If round > 3:** → Continue to STEP 2.10 (max rounds reached)
355
349
 
356
- // User selected a style
357
- const selectedIndex = styleChoice.answers["Style"].charCodeAt(0) - 65;
358
- selectedStyle = scoredOptions[selectedIndex];
350
+ **If user selects a specific style (A, B, C, etc.):**
351
+ 1. Extract the letter (A=0, B=1, C=2, etc.)
352
+ 2. Get the corresponding option from scored list
353
+ 3. Store as selectedStyle
354
+ → Continue to STEP 2.6
359
355
 
360
- // ========== ANIMATION SELECTION ==========
356
+ ### STEP 2.6: Animation Selection
361
357
 
362
- output(`
358
+ Display round header:
359
+ ```
363
360
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
364
- 📋 ROUND ${round}/${maxRounds}: Animation Selection
361
+ 📋 ROUND [current round]/3: Animation Selection
365
362
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
366
- `);
367
-
368
- // Collect all available animations from all sites
369
- const allAnimations = [];
370
-
371
- for (const [siteName, data] of Object.entries(extractedData)) {
372
- // Animation libraries
373
- for (const lib of data.animation_libraries) {
374
- allAnimations.push({
375
- type: 'library',
376
- name: lib.name,
377
- source: siteName,
378
- description: `${lib.name} library detected`
379
- });
380
- }
381
-
382
- // Scroll patterns
383
- for (const pattern of data.scroll_animations.patterns) {
384
- allAnimations.push({
385
- type: 'scroll',
386
- name: pattern,
387
- source: siteName,
388
- description: `Scroll animation: ${pattern}`
389
- });
390
- }
391
-
392
- // Component animations
393
- if (data.component_animations.button_hover !== 'none') {
394
- allAnimations.push({
395
- type: 'component',
396
- name: `Button: ${data.component_animations.button_hover}`,
397
- source: siteName,
398
- description: data.component_animations.button_hover
399
- });
400
- }
401
- if (data.component_animations.card_hover !== 'none') {
402
- allAnimations.push({
403
- type: 'component',
404
- name: `Card: ${data.component_animations.card_hover}`,
405
- source: siteName,
406
- description: data.component_animations.card_hover
407
- });
408
- }
409
- }
363
+ ```
364
+
365
+ **Step 2.6.1: Collect All Available Animations**
366
+
367
+ For each extracted site:
368
+ 1. **From animation_libraries:**
369
+ - For each library: Add entry with type="library", name=lib.name, source=siteName, description="[lib.name] library detected"
370
+
371
+ 2. **From scroll_animations.patterns:**
372
+ - For each pattern: Add entry with type="scroll", name=pattern, source=siteName, description="Scroll animation: [pattern]"
373
+
374
+ 3. **From component_animations:**
375
+ - **If button_hover is not "none":**
376
+ - Add entry with type="component", name="Button: [button_hover]", source=siteName, description=button_hover value
377
+ - **If card_hover is not "none":**
378
+ - Add entry with type="component", name="Card: [card_hover]", source=siteName, description=card_hover value
379
+
380
+ **Step 2.6.2: Display Available Animations**
381
+
382
+ Display header: "🎬 Available Animations (จาก references ทั้งหมด):"
383
+
384
+ For each animation (numbered 1, 2, 3, etc.):
385
+ ```
386
+ [number] [animation name]
387
+ Type: [type]
388
+ Source: [source site]
389
+ Description: [description]
390
+ ```
391
+
392
+ **Step 2.6.3: Ask User to Select Animations**
393
+
394
+ Ask user to choose:
395
+ - Header: "Animations"
396
+ - Multiple selection allowed
397
+ - Question: "เลือก animations ที่ต้องการ (เลือกได้หลายอัน):"
398
+ - Options:
399
+ - For each animation: "[animation name]" - "From [source]: [description]"
400
+
401
+ Parse user's selections and store as selectedAnimations list
402
+
403
+ Continue to STEP 2.7
410
404
 
411
- // Display animations
412
- output(`
413
- 🎬 Available Animations (จาก references ทั้งหมด):
414
-
415
- ${allAnimations.map((anim, i) => `
416
- [${i + 1}] ${anim.name}
417
- Type: ${anim.type}
418
- Source: ${anim.source}
419
- Description: ${anim.description}
420
- `).join('')}
421
- `);
422
-
423
- const animChoice = await AskUserQuestion({
424
- questions: [{
425
- question: "เลือก animations ที่ต้องการ (เลือกได้หลายอัน):",
426
- header: "Animations",
427
- multiSelect: true,
428
- options: allAnimations.map((anim, i) => ({
429
- label: `${anim.name}`,
430
- description: `From ${anim.source}: ${anim.description}`
431
- }))
432
- }]
433
- });
434
-
435
- selectedAnimations = animChoice.answers["Animations"]
436
- ? animChoice.answers["Animations"].split(',').map(s => s.trim())
437
- : [];
438
-
439
- // ========== THEME + DECORATIVE DIRECTION ==========
440
-
441
- output(`
405
+ ### STEP 2.7: Theme & Decorative Direction
406
+
407
+ Display round header:
408
+ ```
442
409
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
443
- 📋 ROUND ${round}/${maxRounds}: Theme & Decorative Direction
410
+ 📋 ROUND [current round]/3: Theme & Decorative Direction
444
411
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
445
- `);
412
+ ```
413
+
414
+ **Step 2.7.1: AI Theme Recommendations**
415
+
416
+ Ask Claude to recommend 3-4 theme options based on project context.
446
417
 
447
- // AI recommends themes based on context
448
- const themePrompt = `
418
+ **Recommendation Prompt:**
419
+ ```
449
420
  Based on project context, recommend 3-4 theme options.
450
421
 
451
422
  Project Context:
452
- - Product Type: ${contextAnalysis.product_type}
453
- - Target Audience: ${contextAnalysis.target_audience?.demographics || 'Unknown'}
454
- - Brand Personality: ${contextAnalysis.brand_personality?.join(', ') || 'Unknown'}
455
- ${Object.keys(contexts).length > 0 ? `- Context Files: ${Object.keys(contexts).join(', ')}` : ''}
456
- ${Object.keys(contexts).length > 0 ? `- Brief Summary: ${Object.values(contexts)[0]?.substring(0, 500)}` : ''}
423
+ - Product Type: [from context analysis]
424
+ - Target Audience: [from context analysis]
425
+ - Brand Personality: [from context analysis]
426
+ [If context files exist: list context file names]
427
+ [If context files exist: include first 500 chars of first file]
457
428
 
458
429
  Return JSON array:
459
430
  [
@@ -467,148 +438,159 @@ Return JSON array:
467
438
  "match_reason": "Why this theme fits the project"
468
439
  }
469
440
  ]
470
- `;
441
+ ```
442
+
443
+ Parse the JSON response to get theme options list.
471
444
 
472
- const themeOptions = await LLM({
473
- prompt: themePrompt,
474
- response_format: 'json'
475
- });
445
+ **Step 2.7.2: Display Theme Options**
476
446
 
477
- output(`
478
- 🎨 Theme Recommendations (based on your project):
479
- `);
447
+ Display header: "🎨 Theme Recommendations (based on your project):"
480
448
 
481
- for (const [index, theme] of themeOptions.entries()) {
482
- output(`
449
+ For each theme option:
450
+ ```
483
451
  ┌─────────────────────────────────────────────────────────────┐
484
- │ Theme ${String.fromCharCode(65 + index)}: ${theme.name}
452
+ │ Theme [Letter]: [theme name]
485
453
  ├─────────────────────────────────────────────────────────────┤
486
454
 
487
- │ 📝 Description: ${theme.description}
488
- │ 🎭 Feeling: ${theme.feeling}
455
+ │ 📝 Description: [description]
456
+ │ 🎭 Feeling: [feeling]
489
457
 
490
458
  │ ✅ Decorative Elements (Use):
491
- ${theme.decorative_elements.map(e => ` ${e}`).join('\n│ ')}
459
+ [element 1]
460
+ │ • [element 2]
461
+ │ ...
492
462
 
493
463
  │ ❌ Avoid:
494
- ${theme.avoid_elements.map(e => ` ${e}`).join('\n│ ')}
464
+ [avoid 1]
465
+ │ • [avoid 2]
466
+ │ ...
495
467
 
496
- │ 🎯 Icons (Lucide): ${theme.icons_suggestion.join(', ')}
468
+ │ 🎯 Icons (Lucide): [icons list]
497
469
 
498
- │ 💡 Why: ${theme.match_reason}
470
+ │ 💡 Why: [match_reason]
499
471
 
500
472
  └─────────────────────────────────────────────────────────────┘
501
- `);
502
- }
503
-
504
- const themeChoice = await AskUserQuestion({
505
- questions: [{
506
- question: "เลือก theme หรือพิมพ์ custom:",
507
- header: "Theme",
508
- multiSelect: false,
509
- options: [
510
- ...themeOptions.map((t, i) => ({
511
- label: `${String.fromCharCode(65 + i)}: ${t.name}`,
512
- description: `${t.feeling} - ${t.decorative_elements.slice(0, 3).join(', ')}`
513
- })),
514
- { label: "No Theme", description: "ไม่ใช้ theme - geometric/abstract" },
515
- { label: "Custom", description: "กำหนด theme เอง" }
516
- ]
517
- }]
518
- });
519
-
520
- if (themeChoice.answers["Theme"] === "Custom") {
521
- output(`พิมพ์ theme ที่ต้องการ (ตัวอย่าง: "อวกาศ - จรวด, ดาวเทียม, ดาว"):`);
522
- const customTheme = await getUserTextInput();
523
- selectedTheme = {
524
- name: 'Custom',
525
- description: customTheme,
526
- decorative_elements: customTheme.split(',').map(s => s.trim()),
527
- avoid_elements: []
528
- };
529
- } else if (themeChoice.answers["Theme"] === "No Theme") {
530
- selectedTheme = {
531
- name: 'Abstract',
532
- description: 'No specific theme - geometric and abstract decorations',
533
- decorative_elements: ['geometric shapes', 'gradients', 'blobs'],
534
- avoid_elements: []
535
- };
536
- } else {
537
- const themeIndex = themeChoice.answers["Theme"].charCodeAt(0) - 65;
538
- selectedTheme = themeOptions[themeIndex];
539
- }
540
-
541
- // ========== CONFIRMATION ==========
473
+ ```
542
474
 
543
- output(`
475
+ **Step 2.7.3: Ask User to Select Theme**
476
+
477
+ Ask user to choose:
478
+ - Header: "Theme"
479
+ - Single selection
480
+ - Question: "เลือก theme หรือพิมพ์ custom:"
481
+ - Options:
482
+ - For each theme: "[Letter]: [name]" - "[feeling] - [first 3 decorative elements]"
483
+ - "No Theme" - "ไม่ใช้ theme - geometric/abstract"
484
+ - "Custom" - "กำหนด theme เอง"
485
+
486
+ **If user selects "Custom":**
487
+ 1. Display prompt: "พิมพ์ theme ที่ต้องการ (ตัวอย่าง: 'อวกาศ - จรวด, ดาวเทียม, ดาว'):"
488
+ 2. Get text input from user
489
+ 3. Build custom theme:
490
+ - name: "Custom"
491
+ - description: [user input]
492
+ - decorative_elements: [split user input by comma and trim]
493
+ - avoid_elements: []
494
+ 4. Store as selectedTheme
495
+
496
+ **If user selects "No Theme":**
497
+ 1. Build abstract theme:
498
+ - name: "Abstract"
499
+ - description: "No specific theme - geometric and abstract decorations"
500
+ - decorative_elements: ["geometric shapes", "gradients", "blobs"]
501
+ - avoid_elements: []
502
+ 2. Store as selectedTheme
503
+
504
+ **If user selects a specific theme (A, B, C, etc.):**
505
+ 1. Extract the letter (A=0, B=1, C=2, etc.)
506
+ 2. Get the corresponding theme from options list
507
+ 3. Store as selectedTheme
508
+
509
+ → Continue to STEP 2.8
510
+
511
+ ### STEP 2.8: Display Summary and Confirmation
512
+
513
+ Display summary header:
514
+ ```
544
515
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
545
516
  ✅ SUMMARY - Please Confirm
546
517
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
547
518
 
548
- 🎨 Style: ${selectedStyle.style} (from ${selectedStyle.site})
549
- Feel: ${selectedStyle.feel}
519
+ 🎨 Style: [selectedStyle.style] (from [selectedStyle.site])
520
+ Feel: [selectedStyle.feel]
550
521
 
551
522
  🎬 Animations Enabled:
552
- ${selectedAnimations.map(a => `${a}`).join('\n') || ' (none selected)'}
523
+ [animation 1]
524
+ ✅ [animation 2]
525
+ (or "(none selected)" if empty)
553
526
 
554
- 🎭 Theme: ${selectedTheme.name}
555
- Decorations: ${selectedTheme.decorative_elements.join(', ')}
556
- Avoid: ${selectedTheme.avoid_elements.join(', ') || '(none)'}
527
+ 🎭 Theme: [selectedTheme.name]
528
+ Decorations: [decorative_elements list]
529
+ Avoid: [avoid_elements list or "(none)"]
557
530
 
558
531
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
559
- `);
560
-
561
- const confirmation = await AskUserQuestion({
562
- questions: [{
563
- question: "ยืนยันการตั้งค่านี้?",
564
- header: "Confirm",
565
- multiSelect: false,
566
- options: [
567
- { label: "Yes, Generate", description: "สร้าง design system ตามนี้" },
568
- { label: "Adjust", description: "ปรับแต่งอีกรอบ" },
569
- { label: "Start Over", description: "เริ่มใหม่ตั้งแต่ต้น" }
570
- ]
571
- }]
572
- });
573
-
574
- if (confirmation.answers["Confirm"] === "Yes, Generate") {
575
- userAccepted = true;
576
- } else if (confirmation.answers["Confirm"] === "Start Over") {
577
- round = 1;
578
- } else {
579
- round++;
580
- }
532
+ ```
533
+
534
+ **Step 2.8.1: Ask User to Confirm**
535
+
536
+ Ask user to confirm:
537
+ - Header: "Confirm"
538
+ - Single selection
539
+ - Question: "ยืนยันการตั้งค่านี้?"
540
+ - Options:
541
+ - "Yes, Generate" - "สร้าง design system ตามนี้"
542
+ - "Adjust" - "ปรับแต่งอีกรอบ"
543
+ - "Start Over" - "เริ่มใหม่ตั้งแต่ต้น"
544
+
545
+ **If user selects "Yes, Generate":**
546
+ - Mark as accepted
547
+ Exit loop, continue to STEP 3
548
+
549
+ **If user selects "Start Over":**
550
+ - Reset round counter to 1
551
+ Go back to STEP 2.1 (start fresh)
552
+
553
+ **If user selects "Adjust":**
554
+ - Increment round counter
555
+ → Continue to STEP 2.9 (check round limit)
556
+
557
+ ### STEP 2.9: Check Round Limit
558
+
559
+ **If current round <= 3:**
560
+ → Go back to STEP 2.1 (new adjustment round)
561
+
562
+ **If current round > 3 (max rounds reached):**
563
+ → Continue to STEP 2.10
581
564
 
582
- if (round > maxRounds && !userAccepted) {
583
- output(`
584
- ⚠️ ครบ ${maxRounds} รอบแล้ว
565
+ ### STEP 2.10: Max Rounds Reached - Force Decision
566
+
567
+ Display warning:
568
+ ```
569
+ ⚠️ ครบ 3 รอบแล้ว
585
570
 
586
571
  แนะนำ:
587
572
  1. รัน /extract กับ reference ใหม่
588
573
  2. หรือ accept แล้วค่อย manual edit ไฟล์ที่สร้าง
589
- `);
590
-
591
- const forceChoice = await AskUserQuestion({
592
- questions: [{
593
- question: "ต้องการ generate ตาม settings ปัจจุบันไหม?",
594
- header: "Force",
595
- multiSelect: false,
596
- options: [
597
- { label: "Yes", description: "Generate ตาม settings ล่าสุด" },
598
- { label: "Cancel", description: "ยกเลิก" }
599
- ]
600
- }]
601
- });
602
-
603
- if (forceChoice.answers["Force"] === "Yes") {
604
- userAccepted = true;
605
- } else {
606
- return output('Design setup cancelled.');
607
- }
608
- }
609
- }
610
574
  ```
611
575
 
576
+ Ask user for final decision:
577
+ - Header: "Force"
578
+ - Single selection
579
+ - Question: "ต้องการ generate ตาม settings ปัจจุบันไหม?"
580
+ - Options:
581
+ - "Yes" - "Generate ตาม settings ล่าสุด"
582
+ - "Cancel" - "ยกเลิก"
583
+
584
+ **If user selects "Yes":**
585
+ - Mark as accepted
586
+ → Continue to STEP 3
587
+
588
+ **If user selects "Cancel":**
589
+ - Display: "Design setup cancelled."
590
+ → STOP (exit command)
591
+
592
+ ---
593
+
612
594
  **Report:**
613
595
  ```
614
596
  ✅ User Selection Complete!
@@ -622,1734 +604,800 @@ ${selectedAnimations.map(a => ` ✅ ${a}`).join('\n') || ' (none selected)'}
622
604
 
623
605
  ---
624
606
 
625
- ## STEP 3: Generate Preview YAMLs
607
+ ## STEP 3: Generate Preview YAMLs (Legacy - Optional)
608
+
609
+ > **Note:** This step is optional and creates preview files for each option. In the new flow, we skip directly to generating the final files.
626
610
 
627
- For each option, create a preview YAML:
611
+ **If you want to generate preview files:**
628
612
 
629
- ```javascript
630
- for (const [index, option] of styleOptions.options.entries()) {
631
- const optionLetter = String.fromCharCode(65 + index); // A, B, C
613
+ For each style option that was presented to the user:
614
+ 1. Assign a letter (A, B, C, etc.)
615
+ 2. Ask Claude to generate an abbreviated YAML preview
632
616
 
633
- const previewPrompt = `
617
+ **Preview Generation Prompt:**
618
+ ```
634
619
  You are generating a preview style guide in YAML format.
635
620
 
636
- Style Direction: ${option.name}
637
- Fit Score: ${option.fit_score}%
638
- Rationale: ${option.rationale}
621
+ Style Direction: [option.name]
622
+ Fit Score: [option.fit_score]%
623
+ Rationale: [option.rationale]
639
624
 
640
625
  Source Mapping:
641
- ${JSON.stringify(option.sources, null, 2)}
626
+ [JSON of option.sources]
642
627
 
643
628
  Customizations:
644
- ${option.customizations.join('\n')}
629
+ [list of option.customizations]
645
630
 
646
631
  Extracted Data (for reference):
647
- ${JSON.stringify(extractedData, null, 2).substring(0, 5000)} // First 5000 chars
632
+ [First 5000 chars of extractedData JSON]
648
633
 
649
634
  Task: Create abbreviated YAML preview with key values only.
650
635
 
651
636
  Format:
652
- \`\`\`yaml
637
+ ```yaml
653
638
  meta:
654
- style_name: "${option.name}"
655
- fit_score: ${option.fit_score}
639
+ style_name: "[option.name]"
640
+ fit_score: [option.fit_score]
656
641
  sources: [list of source sites]
657
642
 
658
643
  colors:
659
644
  primary:
660
- hex: "#..." # From ${option.sources.colors}
645
+ hex: "#..." # From [option.sources.colors]
661
646
  rationale: "Why this color fits"
662
647
  secondary:
663
648
  hex: "#..."
664
649
  # ... 5-10 key colors
665
650
 
666
651
  typography:
667
- font_family: "..." # From ${option.sources.typography}
652
+ font_family: "..." # From [option.sources.typography]
668
653
  h1: { size: "...", weight: "..." }
669
654
  # ... key type styles
670
655
 
671
656
  shadows:
672
- brutal: "..." # From ${option.sources.shadows}
657
+ brutal: "..." # From [option.sources.shadows]
673
658
  # ... 3-5 key shadows
674
659
 
675
660
  spacing:
676
- grid: "..." # From ${option.sources.spacing}
661
+ grid: "..." # From [option.sources.spacing]
677
662
 
678
663
  components:
679
664
  button:
680
- hover_animation: "..." # From ${option.sources.button_hover}
665
+ hover_animation: "..." # From [option.sources.button_hover]
681
666
  description: "..."
682
667
  card:
683
- hover_animation: "..." # From ${option.sources.card_hover}
668
+ hover_animation: "..." # From [option.sources.card_hover]
684
669
  # ... key components
685
670
 
686
671
  border_radius:
687
- values: [...] # From ${option.sources.border_radius}
688
- \`\`\`
672
+ values: [...] # From [option.sources.border_radius]
673
+ ```
689
674
 
690
675
  Return only the YAML content.
691
- `;
676
+ ```
692
677
 
693
- const previewYAML = await LLM({ prompt: previewPrompt });
678
+ 3. Write the preview to file:
679
+ - Path: `design-system/synthesis/options/option-[letter]-[name-kebab-case].yaml`
680
+ - Content: YAML from Claude's response
694
681
 
695
- Write(
696
- `design-system/synthesis/options/option-${optionLetter.toLowerCase()}-${option.name.toLowerCase().replace(/\s+/g, '-')}.yaml`,
697
- previewYAML
698
- );
699
- }
700
- ```
682
+ **Skip this step in most cases** - proceed directly to STEP 3.5
701
683
 
702
684
  ---
703
685
 
704
- ## STEP 3.5: Quick User Input (🆕 v1.4.0)
686
+ ## STEP 3.5: Quick User Input (Legacy - v1.4.0)
687
+
688
+ > **Note:** This step is from an older version and asks for preferences before presenting options. This is now integrated into STEP 2's interactive loop. Can be skipped.
705
689
 
706
- > **NEW:** Ask user for quick feedback before presenting options
690
+ **If you want to collect user preferences upfront:**
707
691
 
708
- ```javascript
709
- output(`
692
+ Display header:
693
+ ```
710
694
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
711
695
  📝 Quick Question
712
696
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
713
- `)
714
-
715
- const userFeedback = await AskUserQuestion({
716
- questions: [{
717
- question: "มีอะไรอยากปรับหรือเน้นเป็นพิเศษไหม? (optional)",
718
- header: "Preferences",
719
- multiSelect: false,
720
- options: [
721
- { label: "ไม่มี ใช้ AI แนะนำ", description: "ให้ AI เลือกสิ่งที่เหมาะสมที่สุด" },
722
- { label: "มีสี CI ของตัวเอง", description: "ระบุสีแบรนด์" },
723
- { label: "ชอบ component เฉพาะ", description: "ชอบ button/card ของเว็บใดเป็นพิเศษ" },
724
- { label: "ปรับอื่นๆ", description: "Typography, shadows, หรืออื่นๆ" }
725
- ]
726
- }]
727
- })
728
-
729
- let userPreferences = { type: 'none' }
730
-
731
- // Process user feedback
732
- if (userFeedback.answers["Preferences"] === "มีสี CI ของตัวเอง") {
733
- output(`
734
- กรุณาระบุสี (HEX format, คั่นด้วย comma):
735
- ตัวอย่าง: #0d7276, #f97316
736
-
737
- สีของคุณ:
738
- `)
739
-
740
- const colorInput = await getUserTextInput()
741
- const colors = colorInput.split(',').map(s => s.trim()).filter(s => s.match(/^#[0-9A-Fa-f]{6}$/))
742
-
743
- if (colors.length > 0) {
744
- userPreferences = {
745
- type: 'custom_colors',
746
- colors: {
747
- primary: colors[0],
748
- secondary: colors[1] || null,
749
- accent: colors[2] || null
750
- }
751
- }
752
- output(`✅ รับสีแล้ว: ${colors.join(', ')}`)
753
- }
754
-
755
- } else if (userFeedback.answers["Preferences"] === "ชอบ component เฉพาะ") {
756
- output(`
757
- ระบุความชอบ (ตัวอย่าง: "ชอบ button ของ motherduck, card ของ gitingest"):
758
- `)
759
-
760
- const preferenceText = await getUserTextInput()
761
- userPreferences = {
762
- type: 'component_preference',
763
- text: preferenceText
764
- }
765
- output(`✅ บันทึกความชอบแล้ว`)
766
-
767
- } else if (userFeedback.answers["Preferences"] === "ปรับอื่นๆ") {
768
- output(`
769
- ระบุสิ่งที่อยากปรับ (ตัวอย่าง: "ใช้ font Inter, shadow แบบ soft"):
770
- `)
771
-
772
- const adjustmentText = await getUserTextInput()
773
- userPreferences = {
774
- type: 'other_adjustment',
775
- text: adjustmentText
776
- }
777
- output(`✅ บันทึกการปรับแต่งแล้ว`)
778
- }
697
+ ```
779
698
 
780
- output(`
699
+ Ask user about special preferences:
700
+ - Header: "Preferences"
701
+ - Single selection
702
+ - Question: "มีอะไรอยากปรับหรือเน้นเป็นพิเศษไหม? (optional)"
703
+ - Options:
704
+ - "ไม่มี ใช้ AI แนะนำ" - "ให้ AI เลือกสิ่งที่เหมาะสมที่สุด"
705
+ - "มีสี CI ของตัวเอง" - "ระบุสีแบรนด์"
706
+ - "ชอบ component เฉพาะ" - "ชอบ button/card ของเว็บใดเป็นพิเศษ"
707
+ - "ปรับอื่นๆ" - "Typography, shadows, หรืออื่นๆ"
708
+
709
+ Initialize userPreferences with type: 'none'
710
+
711
+ **If user selects "มีสี CI ของตัวเอง":**
712
+ 1. Display prompt:
713
+ ```
714
+ กรุณาระบุสี (HEX format, คั่นด้วย comma):
715
+ ตัวอย่าง: #0d7276, #f97316
716
+
717
+ สีของคุณ:
718
+ ```
719
+ 2. Get text input from user
720
+ 3. Parse colors: split by comma, trim, filter only valid HEX format (#RRGGBB)
721
+ 4. **If valid colors found:**
722
+ - Set userPreferences.type = 'custom_colors'
723
+ - Set userPreferences.colors.primary = first color
724
+ - Set userPreferences.colors.secondary = second color (or null)
725
+ - Set userPreferences.colors.accent = third color (or null)
726
+ - Display: "✅ รับสีแล้ว: [colors list]"
727
+
728
+ **If user selects "ชอบ component เฉพาะ":**
729
+ 1. Display prompt: "ระบุความชอบ (ตัวอย่าง: 'ชอบ button ของ motherduck, card ของ gitingest'):"
730
+ 2. Get text input from user
731
+ 3. Set userPreferences.type = 'component_preference'
732
+ 4. Set userPreferences.text = user input
733
+ 5. Display: "✅ บันทึกความชอบแล้ว"
734
+
735
+ **If user selects "ปรับอื่นๆ":**
736
+ 1. Display prompt: "ระบุสิ่งที่อยากปรับ (ตัวอย่าง: 'ใช้ font Inter, shadow แบบ soft'):"
737
+ 2. Get text input from user
738
+ 3. Set userPreferences.type = 'other_adjustment'
739
+ 4. Set userPreferences.text = user input
740
+ 5. Display: "✅ บันทึกการปรับแต่งแล้ว"
741
+
742
+ Display final message:
743
+ ```
781
744
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
782
745
  🔄 กำลังสร้าง style options (พร้อม preferences ของคุณ)...
783
746
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
784
- `)
785
747
  ```
786
748
 
749
+ **In most cases, skip this step** - preferences are handled in STEP 2's interactive loop
750
+
787
751
  ---
788
752
 
789
- ## STEP 4: Present Options to User
753
+ ## STEP 4: Present Options to User (Legacy - Old Flow)
754
+
755
+ > **Note:** This step is from the old flow (v1.x). In the new flow (v2.0+), user selection happens in STEP 2's interactive loop. This step is now DEPRECATED.
790
756
 
791
- ```javascript
792
- output(`
757
+ **Old flow (for reference only):**
758
+
759
+ Display analysis summary:
760
+ ```
793
761
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
794
762
  🎨 Design Direction Analysis Complete
795
763
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
796
764
 
797
765
  Based on:
798
- ${Object.keys(extractedData).length} extracted sites (${Object.keys(extractedData).join(', ')})
799
- ✓ Target: ${contextAnalysis.target_audience.demographics}
800
- ✓ Brand: ${contextAnalysis.brand_personality.join(', ')}
801
- ✓ Product: ${contextAnalysis.product_type}
802
- ${userPreferences.type !== 'none' ? `✓ User preferences: ${JSON.stringify(userPreferences)}` : ''}
766
+ [number] extracted sites ([site names])
767
+ ✓ Target: [target audience]
768
+ ✓ Brand: [brand personality]
769
+ ✓ Product: [product type]
770
+ [If preferences: User preferences: [preferences]]
803
771
 
804
772
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
805
- `);
806
-
807
- for (const [index, option] of styleOptions.options.entries()) {
808
- const optionLetter = String.fromCharCode(65 + index);
809
- const isRecommended = index === 0;
773
+ ```
810
774
 
811
- output(`
812
- Option ${optionLetter}: ${option.name} ${isRecommended ? '⭐ (Recommended)' : ''}
813
- Fit Score: ${option.fit_score}%
775
+ For each style option:
776
+ Display:
777
+ ```
778
+ Option [Letter]: [option.name] [⭐ (Recommended) if first]
779
+ Fit Score: [option.fit_score]%
814
780
 
815
781
  Rationale:
816
- ${option.rationale}
782
+ [option.rationale]
817
783
 
818
784
  Component Sources:
819
- - Colors: ${option.sources.colors}
820
- - Shadows: ${option.sources.shadows}
821
- - Typography: ${option.sources.typography}
822
- - Button hover: ${option.sources.button_hover}
823
- - Card hover: ${option.sources.card_hover}
824
- - Input focus: ${option.sources.input_focus}
825
- - Border radius: ${option.sources.border_radius}
826
- - Overall vibe: ${option.sources.overall_vibe}
785
+ - Colors: [option.sources.colors]
786
+ - Shadows: [option.sources.shadows]
787
+ - Typography: [option.sources.typography]
788
+ - Button hover: [option.sources.button_hover]
789
+ - Card hover: [option.sources.card_hover]
790
+ - Input focus: [option.sources.input_focus]
791
+ - Border radius: [option.sources.border_radius]
792
+ - Overall vibe: [option.sources.overall_vibe]
827
793
 
828
794
  Customizations Applied:
829
- ${option.customizations.map(c => `${c}`).join('\n')}
795
+ [customization 1]
796
+ • [customization 2]
797
+ ...
830
798
 
831
799
  Advantages:
832
- ${option.advantages.map(a => `${a}`).join('\n')}
800
+ [advantage 1]
801
+ ✅ [advantage 2]
802
+ ...
833
803
 
834
804
  Disadvantages:
835
- ${option.disadvantages.map(d => ` ⚠️ ${d}`).join('\n')}
805
+ ⚠️ [disadvantage 1]
806
+ ⚠️ [disadvantage 2]
807
+ ...
836
808
 
837
- Preview: design-system/synthesis/options/option-${optionLetter.toLowerCase()}-${option.name.toLowerCase().replace(/\s+/g, '-')}.yaml
809
+ Preview: design-system/synthesis/options/option-[letter]-[name-kebab].yaml
838
810
 
839
811
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
840
- `);
841
- }
812
+ ```
842
813
 
843
- // Ask user to select
844
- const userChoice = await AskUserQuestion({
845
- questions: [{
846
- question: "Select design direction:",
847
- header: "Style",
848
- multiSelect: false,
849
- options: styleOptions.options.map((opt, i) => ({
850
- label: `${String.fromCharCode(65 + i)}: ${opt.name}`,
851
- description: `${opt.fit_score}% fit - ${opt.rationale.substring(0, 100)}...`
852
- }))
853
- }]
854
- });
814
+ Ask user to select:
815
+ - Header: "Style"
816
+ - Single selection
817
+ - Question: "Select design direction:"
818
+ - Options:
819
+ - For each option: "[Letter]: [name]" - "[score]% fit - [first 100 chars of rationale]..."
855
820
 
856
- const selectedIndex = userChoice.answers["Style"].charCodeAt(0) - 65;
857
- const selectedOption = styleOptions.options[selectedIndex];
858
- ```
821
+ Extract selected index and get corresponding option.
859
822
 
860
823
  **Report:**
861
824
  ```
862
- ✅ Style Selected: ${selectedOption.name}
825
+ ✅ Style Selected: [selectedOption.name]
863
826
 
864
827
  🔄 Generating comprehensive design system...
865
828
  ```
866
829
 
867
- ---
868
-
869
- ## STEP 5: Generate Final Design System (Legacy - See STEP 5.7)
870
-
871
- ```javascript
872
- const styleGuidePrompt = `
873
- You are generating the final, comprehensive design system file.
874
-
875
- Selected Style: ${selectedOption.name}
876
- Fit Score: ${selectedOption.fit_score}%
877
- Rationale: ${selectedOption.rationale}
878
-
879
- Source Mapping:
880
- ${JSON.stringify(selectedOption.sources, null, 2)}
881
-
882
- Customizations:
883
- ${selectedOption.customizations.join('\n')}
884
-
885
- Full Extracted Data:
886
- ${JSON.stringify(extractedData, null, 2)}
887
-
888
- Preview YAML:
889
- ${Read(`design-system/synthesis/options/option-${String.fromCharCode(65 + selectedIndex).toLowerCase()}-${selectedOption.name.toLowerCase().replace(/\s+/g, '-')}.yaml`)}
890
-
891
- Project Context:
892
- - Product: ${contextAnalysis.product_type}
893
- - Audience: ${contextAnalysis.target_audience.demographics}
894
- - Brand: ${contextAnalysis.brand_personality.join(', ')}
895
-
896
- Task: Generate complete design system (1500-2000 lines) with ALL 17 sections.
897
-
898
- Follow this format:
899
-
900
- # [Project Name] Design System - Style Guide (${selectedOption.name})
901
-
902
- > **Source:** Based on ${Object.keys(extractedData).join(', ')}, customized for [Project]
903
- > **Date:** ${new Date().toISOString().split('T')[0]}
904
- > **Design Style:** ${selectedOption.name}
905
- > **Tech Stack:** Universal (Framework-agnostic)
906
- > **Primary Color:** [from preview YAML]
907
-
908
- ---
909
-
910
- ## Quick Reference
911
-
912
- ### Most Used Patterns
913
-
914
- | Pattern | Code |
915
- |---------|------|
916
- [Table with most-used component patterns with exact Tailwind classes]
917
-
918
- ### Design Tokens Summary
919
-
920
- \`\`\`json
921
- {
922
- "colors": { ... },
923
- "spacing": { ... },
924
- "typography": { ... },
925
- "borderRadius": { ... },
926
- "shadows": { ... }
927
- }
928
- \`\`\`
830
+ **In current version (v2.0+), skip this step** - user selection is handled in STEP 2
929
831
 
930
832
  ---
931
833
 
932
- ## Table of Contents
933
-
934
- 1. [Overview](#1-overview)
935
- 2. [Design Philosophy](#2-design-philosophy)
936
- 3. [Color Palette](#3-color-palette)
937
- ... (all 17)
938
-
939
- ---
940
-
941
- ## 1. Overview
942
-
943
- **Summary:**
944
- This design system is based on **${selectedOption.name}** aesthetics...
945
-
946
- **Key Characteristics:**
947
- - [List from extracted data + customizations]
948
-
949
- **Tech Stack:**
950
- - Framework: Universal
951
- - Styling: Tailwind CSS recommended
952
- - Font: [from typography source]
953
-
954
- **Goals:**
955
- - [Derived from rationale + advantages]
956
-
957
- ---
834
+ ## STEP 5: Generate Final Design System (Legacy - Deprecated in v2.0+)
958
835
 
959
- ## 2. Design Philosophy
836
+ > **Note:** This step is from the old flow (v1.x). In the current flow (v2.0+), design system generation happens in STEP 5.5 (data.yaml), STEP 5.6 (patterns/*.md), and STEP 5.7 (README.md). This step is now DEPRECATED.
960
837
 
961
- **Core Principles:**
838
+ **Old flow (for reference only):**
962
839
 
963
- 1. **[Principle 1 from rationale]**
964
- - [Description]
840
+ This step would generate a comprehensive 1500-2000 line README.md by:
965
841
 
966
- 2. **[Principle 2]**
967
- - [Description]
842
+ 1. Preparing a prompt for Claude with:
843
+ - Selected option details (name, fit score, rationale)
844
+ - Source mapping (which site provided which design elements)
845
+ - Customizations applied
846
+ - Full extracted data from all sites
847
+ - Preview YAML content
848
+ - Project context (product type, audience, brand)
968
849
 
969
- ... (derive from ${selectedOption.name} characteristics + rationale)
850
+ 2. The prompt would request a complete design system markdown file with:
851
+ - Header with metadata (source, date, style, tech stack, primary color)
852
+ - Quick reference section (most-used patterns table, design tokens JSON)
853
+ - Table of contents (all 17 sections)
854
+ - Section 1: Overview (summary, characteristics, tech stack, goals)
855
+ - Section 2: Design Philosophy (core principles, visual identity, differentiators, UX goals)
856
+ - Section 3: Color Palette (primary/secondary colors with hex, usage, psychology, source, CSS variables, Tailwind classes)
857
+ - Section 4: Typography (font family, weights, text styles for all headings with exact Tailwind classes and sources)
858
+ - Section 5: Spacing System (grid base, scale array from source)
859
+ - Section 6: Component Styles (buttons, cards, etc. with exact classes, animations, sources)
860
+ - Section 7: Shadows & Elevation (levels and usage from source)
861
+ - Sections 8-16: [Other design system sections]
862
+ - Section 17: Additional Sections (implementation best practices, accessibility guidelines, critical DO/DON'T rules)
863
+ - Footer with project name, date, sources
970
864
 
971
- **Visual Identity:**
972
- ${selectedOption.rationale}
865
+ 3. Ask Claude's LLM to generate the content (max 16000 tokens)
973
866
 
974
- **Key Differentiators:**
975
- ${selectedOption.advantages.slice(0, 3).map(a => `- ${a}`).join('\n')}
867
+ 4. Write the generated content to `design-system/README.md`
976
868
 
977
- **User Experience Goals:**
978
- - First Impression: [based on style name]
979
- - During Use: [based on style name]
980
- - Long-term: [based on style name]
869
+ **In current version (v2.0+), skip this step** - generation is split into STEP 5.5, 5.6, and 5.7
981
870
 
982
871
  ---
983
872
 
984
- ## 3. Color Palette
873
+ ## STEP 5.5: Generate tokens.json and data.yaml (Enhanced v2.0.0)
985
874
 
986
- [Extract from preview YAML + source data]
875
+ > **Enhanced v2.0.0:** Now includes style, theme, animations, decorative_direction, and patterns_index
987
876
 
988
- ### Primary Colors
877
+ Display progress:
878
+ ```
879
+ 🔄 Generating enhanced tokens.json...
880
+ ```
989
881
 
990
- **Primary ([Color Name])**
991
- - **Color**: [hex] (rgb(...))
992
- - **Usage**: [from source data]
993
- - **Psychology**: [analysis]
994
- - **Source**: ${selectedOption.sources.colors}
995
- - **CSS Variable**: \`var(--color-primary)\`
996
- - **Tailwind**: \`bg-primary\`, \`text-primary\`, \`border-primary\`
882
+ ### Build Tokens Data Structure
883
+
884
+ Create a data structure with the following sections:
885
+
886
+ **1. Schema & Meta:**
887
+ - schema: "https://json-schema.org/draft-07/schema"
888
+ - version: "2.0.0"
889
+ - meta.generated_at: current timestamp (ISO format)
890
+ - meta.generated_by: "/designsetup command v2.0.0"
891
+ - meta.source_sites: list of extracted site names
892
+ - meta.description: "Design tokens for agents (~800 tokens). Human-readable guide: README.md"
893
+
894
+ **2. Style (from user selection in STEP 2):**
895
+ - style.name: selectedStyle.style
896
+ - style.confidence: selectedStyle.confidence
897
+ - style.characteristics: selectedStyle.characteristics
898
+ - style.feel: selectedStyle.feel
899
+ - style.source_site: selectedStyle.site
900
+
901
+ **3. Theme (from user selection in STEP 2.7):**
902
+ - theme.name: selectedTheme.name
903
+ - theme.description: selectedTheme.description
904
+ - theme.feeling: selectedTheme.feeling (or description if feeling not set)
905
+ - theme.decorative_elements.use: selectedTheme.decorative_elements
906
+ - theme.decorative_elements.avoid: selectedTheme.avoid_elements
907
+ - theme.icons_suggestion: selectedTheme.icons_suggestion (or ["Lucide icons"] as fallback)
908
+
909
+ **4. Animations (from user selection in STEP 2.6):**
910
+ - animations.enabled: true if selectedAnimations has items, false otherwise
911
+ - animations.libraries: extractedData[selectedStyle.site].animation_libraries (or empty array)
912
+ - animations.selected_patterns: selectedAnimations list
913
+ - animations.scroll_animations.enabled: true if any selected animation includes 'scroll', 'parallax', 'fade', or 'stacking'
914
+ - animations.scroll_animations.patterns: extractedData[selectedStyle.site].scroll_animations.patterns (or empty)
915
+ - animations.component_animations.button_hover: from selected site's data (or "scale + shadow" as fallback)
916
+ - animations.component_animations.card_hover: from selected site's data (or "translateY + shadow" as fallback)
917
+ - animations.component_animations.input_focus: from selected site's data (or "ring" as fallback)
918
+ - animations.duration.fast: "150ms"
919
+ - animations.duration.normal: "200ms"
920
+ - animations.duration.slow: "300ms"
921
+ - animations.easing.default: "ease-in-out"
922
+ - animations.easing.bounce: "cubic-bezier(0.68, -0.55, 0.265, 1.55)"
923
+
924
+ **5. Colors (from selectedStyle):**
925
+ - colors.primary.DEFAULT: selectedStyle.colors[0] (or "#0d7276" as fallback)
926
+ - colors.primary.foreground: "#ffffff"
927
+ - colors.primary.hover: darken primary color by 10%
928
+ - colors.primary.tailwind: "bg-primary, text-primary, border-primary"
929
+ - colors.secondary.DEFAULT: selectedStyle.colors[1] (or "#64748b" as fallback)
930
+ - colors.secondary.foreground: "#ffffff"
931
+ - colors.secondary.hover: darken secondary color by 10%
932
+ - colors.accent.DEFAULT: selectedStyle.colors[2] (or primary color, or "#f97316")
933
+ - colors.accent.foreground: "#ffffff"
934
+ - colors.background: { DEFAULT: "#ffffff", muted: "#f1f5f9", subtle: "#f8fafc" }
935
+ - colors.foreground: { DEFAULT: "#0a0a0a", muted: "#64748b", subtle: "#94a3b8" }
936
+ - colors.border: { DEFAULT: "#e2e8f0", hover: "#cbd5e1", focus: primary color }
937
+ - colors.semantic: { success: "#10b981", warning: "#f59e0b", error: "#ef4444", info: "#3b82f6" }
938
+
939
+ **Color Darkening Logic:**
940
+ To darken a hex color by a percentage:
941
+ 1. Remove '#' prefix and convert to integer
942
+ 2. Calculate amount: round(2.55 * percent)
943
+ 3. Extract RGB: R = (num >> 16), G = (num >> 8 & 0xFF), B = (num & 0xFF)
944
+ 4. Subtract amount from each: max(R - amount, 0), max(G - amount, 0), max(B - amount, 0)
945
+ 5. Recombine and convert back to hex with '#' prefix
946
+
947
+ **6. Typography (from selected site):**
948
+ - typography.font_family.sans: extractedData[selectedStyle.site].typography.fonts[0] (or "'Inter', sans-serif")
949
+ - typography.font_family.mono: "'Fira Code', monospace"
950
+ - typography.font_size: { xs: "12px", sm: "14px", base: "16px", lg: "18px", xl: "20px", 2xl: "24px", 3xl: "30px", 4xl: "36px", 5xl: "48px" }
951
+ - typography.font_weight: { normal: "400", medium: "500", semibold: "600", bold: "700" }
952
+ - typography.headings: { h1: "text-5xl font-bold", h2: "text-4xl font-bold", h3: "text-3xl font-semibold", h4: "text-2xl font-semibold", h5: "text-xl font-medium", h6: "text-lg font-medium" }
953
+
954
+ **7. Spacing (from selected site):**
955
+ - spacing.scale: extractedData[selectedStyle.site].spacing.common (or [4, 8, 12, 16, 24, 32, 48, 64, 96])
956
+ - spacing.grid_base: extractedData[selectedStyle.site].spacing.grid_base (or "8px")
957
+ - spacing.common_patterns: { component_padding: "p-4 (16px) or p-6 (24px)", section_gap: "gap-8 (32px) or gap-12 (48px)", layout_margin: "mt-16 (64px) or mt-24 (96px)" }
958
+
959
+ **8. Shadows (from selected site):**
960
+ - shadows.values: extractedData[selectedStyle.site].shadows (or default array)
961
+ - shadows.usage: { cards: "shadow-md", dropdowns: "shadow-lg", modals: "shadow-xl", buttons_hover: "shadow-sm" }
962
+
963
+ **9. Borders (from selected site):**
964
+ - borders.radius: extractedData[selectedStyle.site].border_radius (or ["4px", "8px", "12px", "9999px"])
965
+ - borders.usage: { inputs: "rounded-md", buttons: "rounded-lg", cards: "rounded-xl", avatars: "rounded-full" }
966
+
967
+ **10. Patterns Index:**
968
+ - patterns_index.buttons: "design-system/patterns/buttons.md"
969
+ - patterns_index.scroll_animations: "design-system/patterns/scroll-animations.md"
970
+ - patterns_index.decorations: "design-system/patterns/decorations.md"
971
+ - patterns_index.cards: "design-system/patterns/cards.md"
972
+ - patterns_index.forms: "design-system/patterns/forms.md"
973
+
974
+ **11. Component Library:**
975
+ - component_library.name: "shadcn/ui"
976
+ - component_library.install_command: "npx shadcn-ui@latest init"
977
+ - component_library.common_components: ["button", "card", "input", "select", "dialog", "dropdown-menu", "badge", "avatar", "tooltip"]
978
+
979
+ **12. Critical Rules:**
980
+ - critical_rules.colors: ["❌ NO hardcoded hex values", "✅ USE theme tokens (bg-primary, text-foreground)"]
981
+ - critical_rules.spacing: ["❌ NO arbitrary values (p-5, gap-7)", "✅ USE spacing scale (p-4, p-6, gap-8)"]
982
+ - critical_rules.consistency: ["❌ NO mixing patterns", "✅ USE consistent patterns from tokens"]
983
+
984
+ ### Generate data.yaml
985
+
986
+ Call the helper function (see Helper section below) to generate YAML format with:
987
+ - Tokens data from above
988
+ - Psychology data from extractedData[selectedStyle.site]
989
+ - All design tokens in YAML format
990
+
991
+ Write to file: `design-system/data.yaml`
992
+
993
+ Display confirmation:
994
+ ```
995
+ ✅ data.yaml generated (~300 lines)
996
+ ```
997
997
 
998
- ... continue all colors from preview YAML ...
998
+ Continue to STEP 5.6
999
999
 
1000
1000
  ---
1001
1001
 
1002
- ## 4. Typography
1002
+ ## STEP 5.6: Generate patterns/*.md Files
1003
1003
 
1004
- [Extract from source data]
1004
+ > **Code patterns for agents** - Selective loading based on page type
1005
1005
 
1006
- **Font Family:**
1007
- \`\`\`css
1008
- font-family: [from ${selectedOption.sources.typography}]
1009
- \`\`\`
1006
+ ### STEP 5.6.1: Display Progress Message
1010
1007
 
1011
- **Font Weights:**
1012
- [Table from source data]
1008
+ Display progress message:
1009
+ ```
1010
+ 🔄 Generating pattern files...
1011
+ ```
1013
1012
 
1014
- **Text Styles:**
1013
+ ### STEP 5.6.2: Create Patterns Directory
1015
1014
 
1016
- ### Headings
1015
+ Create the patterns directory:
1016
+ - Path: `design-system/patterns`
1017
1017
 
1018
- **H1 - [Usage]**
1019
- \`\`\`html
1020
- <h1 className="[exact Tailwind classes from source]">
1021
- Example Text
1022
- </h1>
1023
- \`\`\`
1024
- - **Size**: [from source]
1025
- - **Weight**: [from source]
1026
- - **Source**: ${selectedOption.sources.typography}
1018
+ ### STEP 5.6.3: Generate buttons.md
1027
1019
 
1028
- ... continue all typography ...
1020
+ Build the buttons pattern content with these sections:
1029
1021
 
1030
- ---
1022
+ 1. **Header metadata:**
1023
+ - Source: selectedStyle.site
1024
+ - Style: selectedStyle.style
1025
+ - Load when: "Any UI page"
1031
1026
 
1032
- ## 5. Spacing System
1027
+ 2. **Button variants** (each with TSX code example):
1028
+ - Primary Button (with conditional hover based on tokensData.animations.component_animations.button_hover)
1029
+ - Secondary Button
1030
+ - Ghost Button
1031
+ - Outline Button
1032
+ - Icon Button
1033
1033
 
1034
- [Extract from ${selectedOption.sources.spacing}]
1034
+ 3. **Button sizes:**
1035
+ - Small: px-3 py-1.5 text-sm rounded-md
1036
+ - Medium (default): px-4 py-2 text-base rounded-lg
1037
+ - Large: px-6 py-3 text-lg rounded-lg
1035
1038
 
1036
- **Grid Base:** [from source data]
1039
+ ### STEP 5.6.4: Generate scroll-animations.md
1037
1040
 
1038
- **Scale:** [array from source]
1041
+ Build the scroll animations pattern content with these sections:
1039
1042
 
1040
- ---
1043
+ 1. **Header metadata:**
1044
+ - Source: selectedStyle.site
1045
+ - Style: selectedStyle.style
1046
+ - Load when: "Landing pages, marketing pages"
1047
+ - Libraries: List from tokensData.animations.libraries or "CSS/Tailwind"
1041
1048
 
1042
- ## 6. Component Styles
1049
+ 2. **Enabled Patterns list:** List from selectedAnimations or "No scroll animations selected"
1043
1050
 
1044
- ### 6.2 Button Component
1051
+ 3. **Code examples** (TSX):
1052
+ - Fade In on Scroll (CSS with IntersectionObserver)
1053
+ - Stacking Cards (GSAP ScrollTrigger)
1054
+ - Parallax Section (CSS with scroll handler)
1055
+ - Slide In from Side (Left and Right animations)
1045
1056
 
1046
- **Primary Button**
1047
- \`\`\`tsx
1048
- <button className="[exact classes from ${selectedOption.sources.button_hover}]">
1049
- Click me
1050
- </button>
1051
- \`\`\`
1057
+ Write the content to `design-system/patterns/scroll-animations.md`
1052
1058
 
1053
- **Animation:**
1054
- - **Type**: [from extracted animations]
1055
- - **Description**: [from animations data]
1056
- - **Source**: ${selectedOption.sources.button_hover}
1057
- - **Duration**: [from source]
1059
+ ### STEP 5.6.5: Generate decorations.md
1058
1060
 
1059
- ... continue all components from all sources ...
1061
+ Build the decorations pattern content with these sections:
1060
1062
 
1061
- ---
1063
+ 1. **Header metadata:**
1064
+ - Theme: selectedTheme.name
1065
+ - Load when: "Landing pages, marketing pages (NOT dashboards)"
1062
1066
 
1063
- ## 7. Shadows & Elevation
1067
+ 2. **Theme Direction:**
1068
+ - USE These Elements: List from selectedTheme.decorative_elements
1069
+ - AVOID These Elements: List from selectedTheme.avoid_elements or "(none specified)"
1070
+ - Suggested Icons (Lucide): List from selectedTheme.icons_suggestion or "Default Lucide icons"
1064
1071
 
1065
- [Extract from ${selectedOption.sources.shadows}]
1072
+ 3. **Code examples** (TSX):
1073
+ - Gradient Background (subtle overlay and mesh gradient)
1074
+ - Blob Shapes (animated blob with CSS keyframes)
1075
+ - Grid Pattern (dot grid and line grid backgrounds)
1076
+ - Floating Elements (floating icons with animation)
1077
+ - Dividers & Separators (wave divider SVG and gradient line)
1066
1078
 
1067
- ... continue all 17 sections ...
1079
+ Write the content to `design-system/patterns/decorations.md`
1068
1080
 
1069
- ---
1081
+ ### STEP 5.6.6: Generate cards.md
1070
1082
 
1071
- ## 17. Additional Sections
1083
+ Build the cards pattern content with these sections:
1072
1084
 
1073
- ### 17.1 Implementation Best Practices
1085
+ 1. **Header metadata:**
1086
+ - Source: selectedStyle.site
1087
+ - Style: selectedStyle.style
1088
+ - Load when: "Any UI page"
1074
1089
 
1075
- **Design Token Usage:**
1076
- - Use [font] for everything
1077
- - Use [spacing] grid
1078
- - Use [shadow style]
1079
- - Never [anti-pattern from disadvantages]
1090
+ 2. **Card variants** (each with TSX code example):
1091
+ - Default Card
1092
+ - Interactive Card (with conditional hover based on tokensData.animations.component_animations.card_hover)
1093
+ - Feature Card (with icon container)
1094
+ - Pricing Card (with popular badge, price, features list, CTA button)
1095
+ - Testimonial Card (with avatar, name, title, quote)
1080
1096
 
1081
- ### 17.2 Accessibility Guidelines
1097
+ Write the content to `design-system/patterns/cards.md`
1082
1098
 
1083
- [Standard accessibility section]
1099
+ ### STEP 5.6.7: Generate forms.md
1084
1100
 
1085
- ### 17.3 Critical Rules
1101
+ Build the forms pattern content with these sections:
1086
1102
 
1087
- **DO:**
1088
- ${selectedOption.advantages.map(a => `- ✅ ${a}`).join('\n')}
1103
+ 1. **Header metadata:**
1104
+ - Source: selectedStyle.site
1105
+ - Style: selectedStyle.style
1106
+ - Load when: "Auth pages, settings, any form UI"
1089
1107
 
1090
- **DON'T:**
1091
- ${selectedOption.disadvantages.map(d => `- ${d}`).join('\n')}
1092
-
1093
- ---
1108
+ 2. **Form elements** (each with TSX code example):
1109
+ - Input Field (with label, input, helper text)
1110
+ - Input with Error (error state styling and error message)
1111
+ - Select Field (dropdown)
1112
+ - Checkbox (with label)
1113
+ - Form Layout (complete form with submit button)
1094
1114
 
1095
- *Customized for [Project] from ${selectedOption.name} design principles*
1096
- *Date: ${new Date().toISOString().split('T')[0]}*
1097
- *Sources: ${Object.keys(extractedData).join(', ')}*
1098
- `;
1115
+ Write the content to `design-system/patterns/forms.md`
1099
1116
 
1100
- const styleGuideMD = await LLM({
1101
- prompt: styleGuidePrompt,
1102
- max_tokens: 16000
1103
- });
1117
+ ### STEP 5.6.8: Display Completion Message
1104
1118
 
1105
- Write('design-system/README.md', styleGuideMD);
1119
+ Display completion message:
1106
1120
  ```
1107
-
1108
- ---
1109
-
1110
- ## STEP 5.5: Generate tokens.json (Enhanced v2.0.0)
1111
-
1112
- > **Enhanced v2.0.0:** tokens.json now includes style, theme, animations, decorative_direction, and patterns_index
1113
-
1114
- ```javascript
1115
- output(`
1116
- 🔄 Generating enhanced tokens.json...
1117
- `);
1118
-
1119
- // Build tokens.json from user selections + extracted data
1120
- const tokensData = {
1121
- "$schema": "https://json-schema.org/draft-07/schema",
1122
- "version": "2.0.0",
1123
- "meta": {
1124
- "generated_at": new Date().toISOString(),
1125
- "generated_by": "/designsetup command v2.0.0",
1126
- "source_sites": Object.keys(extractedData),
1127
- "description": "Design tokens for agents (~800 tokens). Human-readable guide: README.md"
1128
- },
1129
-
1130
- // ========== NEW: Style & Theme (from user selection) ==========
1131
- "style": {
1132
- "name": selectedStyle.style,
1133
- "confidence": selectedStyle.confidence,
1134
- "characteristics": selectedStyle.characteristics,
1135
- "feel": selectedStyle.feel,
1136
- "source_site": selectedStyle.site
1137
- },
1138
-
1139
- "theme": {
1140
- "name": selectedTheme.name,
1141
- "description": selectedTheme.description,
1142
- "feeling": selectedTheme.feeling || selectedTheme.description,
1143
- "decorative_elements": {
1144
- "use": selectedTheme.decorative_elements,
1145
- "avoid": selectedTheme.avoid_elements
1146
- },
1147
- "icons_suggestion": selectedTheme.icons_suggestion || ["Lucide icons"]
1148
- },
1149
-
1150
- // ========== NEW: Animations (from user selection) ==========
1151
- "animations": {
1152
- "enabled": selectedAnimations.length > 0,
1153
- "libraries": extractedData[selectedStyle.site]?.animation_libraries || [],
1154
- "selected_patterns": selectedAnimations,
1155
- "scroll_animations": {
1156
- "enabled": selectedAnimations.some(a =>
1157
- a.includes('scroll') || a.includes('parallax') || a.includes('fade') || a.includes('stacking')
1158
- ),
1159
- "patterns": extractedData[selectedStyle.site]?.scroll_animations?.patterns || []
1160
- },
1161
- "component_animations": {
1162
- "button_hover": extractedData[selectedStyle.site]?.component_animations?.button_hover || "scale + shadow",
1163
- "card_hover": extractedData[selectedStyle.site]?.component_animations?.card_hover || "translateY + shadow",
1164
- "input_focus": extractedData[selectedStyle.site]?.component_animations?.input_focus || "ring"
1165
- },
1166
- "duration": {
1167
- "fast": "150ms",
1168
- "normal": "200ms",
1169
- "slow": "300ms"
1170
- },
1171
- "easing": {
1172
- "default": "ease-in-out",
1173
- "bounce": "cubic-bezier(0.68, -0.55, 0.265, 1.55)"
1174
- }
1175
- },
1176
-
1177
- // ========== Colors (from selected style's source) ==========
1178
- "colors": {
1179
- "primary": {
1180
- "DEFAULT": selectedStyle.colors[0] || "#0d7276",
1181
- "foreground": "#ffffff",
1182
- "hover": darkenColor(selectedStyle.colors[0] || "#0d7276", 10),
1183
- "tailwind": "bg-primary, text-primary, border-primary"
1184
- },
1185
- "secondary": {
1186
- "DEFAULT": selectedStyle.colors[1] || "#64748b",
1187
- "foreground": "#ffffff",
1188
- "hover": darkenColor(selectedStyle.colors[1] || "#64748b", 10)
1189
- },
1190
- "accent": {
1191
- "DEFAULT": selectedStyle.colors[2] || selectedStyle.colors[0] || "#f97316",
1192
- "foreground": "#ffffff"
1193
- },
1194
- "background": {
1195
- "DEFAULT": "#ffffff",
1196
- "muted": "#f1f5f9",
1197
- "subtle": "#f8fafc"
1198
- },
1199
- "foreground": {
1200
- "DEFAULT": "#0a0a0a",
1201
- "muted": "#64748b",
1202
- "subtle": "#94a3b8"
1203
- },
1204
- "border": {
1205
- "DEFAULT": "#e2e8f0",
1206
- "hover": "#cbd5e1",
1207
- "focus": selectedStyle.colors[0] || "#0d7276"
1208
- },
1209
- "semantic": {
1210
- "success": "#10b981",
1211
- "warning": "#f59e0b",
1212
- "error": "#ef4444",
1213
- "info": "#3b82f6"
1214
- }
1215
- },
1216
-
1217
- // ========== Typography (from extracted data) ==========
1218
- "typography": {
1219
- "font_family": {
1220
- "sans": extractedData[selectedStyle.site]?.typography?.fonts[0] || "'Inter', sans-serif",
1221
- "mono": "'Fira Code', monospace"
1222
- },
1223
- "font_size": {
1224
- "xs": "12px", "sm": "14px", "base": "16px", "lg": "18px",
1225
- "xl": "20px", "2xl": "24px", "3xl": "30px", "4xl": "36px", "5xl": "48px"
1226
- },
1227
- "font_weight": {
1228
- "normal": "400", "medium": "500", "semibold": "600", "bold": "700"
1229
- },
1230
- "headings": {
1231
- "h1": "text-5xl font-bold",
1232
- "h2": "text-4xl font-bold",
1233
- "h3": "text-3xl font-semibold",
1234
- "h4": "text-2xl font-semibold",
1235
- "h5": "text-xl font-medium",
1236
- "h6": "text-lg font-medium"
1237
- }
1238
- },
1239
-
1240
- // ========== Spacing (from extracted data) ==========
1241
- "spacing": {
1242
- "scale": extractedData[selectedStyle.site]?.spacing?.common || [4, 8, 12, 16, 24, 32, 48, 64, 96],
1243
- "grid_base": extractedData[selectedStyle.site]?.spacing?.grid_base || "8px",
1244
- "common_patterns": {
1245
- "component_padding": "p-4 (16px) or p-6 (24px)",
1246
- "section_gap": "gap-8 (32px) or gap-12 (48px)",
1247
- "layout_margin": "mt-16 (64px) or mt-24 (96px)"
1248
- }
1249
- },
1250
-
1251
- // ========== Shadows (from extracted data) ==========
1252
- "shadows": {
1253
- "values": extractedData[selectedStyle.site]?.shadows || [
1254
- "0 1px 2px 0 rgb(0 0 0 / 0.05)",
1255
- "0 4px 6px -1px rgb(0 0 0 / 0.1)",
1256
- "0 10px 15px -3px rgb(0 0 0 / 0.1)"
1257
- ],
1258
- "usage": {
1259
- "cards": "shadow-md",
1260
- "dropdowns": "shadow-lg",
1261
- "modals": "shadow-xl",
1262
- "buttons_hover": "shadow-sm"
1263
- }
1264
- },
1265
-
1266
- // ========== Borders (from extracted data) ==========
1267
- "borders": {
1268
- "radius": extractedData[selectedStyle.site]?.border_radius || ["4px", "8px", "12px", "9999px"],
1269
- "usage": {
1270
- "inputs": "rounded-md",
1271
- "buttons": "rounded-lg",
1272
- "cards": "rounded-xl",
1273
- "avatars": "rounded-full"
1274
- }
1275
- },
1276
-
1277
- // ========== NEW: Patterns Index (references to patterns/*.md) ==========
1278
- "patterns_index": {
1279
- "buttons": "design-system/patterns/buttons.md",
1280
- "scroll_animations": "design-system/patterns/scroll-animations.md",
1281
- "decorations": "design-system/patterns/decorations.md",
1282
- "cards": "design-system/patterns/cards.md",
1283
- "forms": "design-system/patterns/forms.md"
1284
- },
1285
-
1286
- // ========== Component Library ==========
1287
- "component_library": {
1288
- "name": "shadcn/ui",
1289
- "install_command": "npx shadcn-ui@latest init",
1290
- "common_components": ["button", "card", "input", "select", "dialog", "dropdown-menu", "badge", "avatar", "tooltip"]
1291
- },
1292
-
1293
- // ========== Critical Rules ==========
1294
- "critical_rules": {
1295
- "colors": [
1296
- "❌ NO hardcoded hex values",
1297
- "✅ USE theme tokens (bg-primary, text-foreground)"
1298
- ],
1299
- "spacing": [
1300
- "❌ NO arbitrary values (p-5, gap-7)",
1301
- "✅ USE spacing scale (p-4, p-6, gap-8)"
1302
- ],
1303
- "consistency": [
1304
- "❌ NO mixing patterns",
1305
- "✅ USE consistent patterns from tokens"
1306
- ]
1307
- }
1308
- };
1309
-
1310
- // Helper function to darken color
1311
- function darkenColor(hex, percent) {
1312
- const num = parseInt(hex.replace('#', ''), 16);
1313
- const amt = Math.round(2.55 * percent);
1314
- const R = Math.max((num >> 16) - amt, 0);
1315
- const G = Math.max((num >> 8 & 0x00FF) - amt, 0);
1316
- const B = Math.max((num & 0x0000FF) - amt, 0);
1317
- return '#' + (0x1000000 + R * 0x10000 + G * 0x100 + B).toString(16).slice(1);
1318
- }
1319
-
1320
- // Write data.yaml (includes psychology from extracted sites)
1321
- const dataYaml = generateDataYaml(tokensData, extractedData, selectedStyle);
1322
- Write('design-system/data.yaml', dataYaml);
1323
- output(`✅ data.yaml generated (~300 lines)`);
1324
- ```
1325
-
1326
- ---
1327
-
1328
- ## STEP 5.6: Generate patterns/*.md Files
1329
-
1330
- > **Code patterns for agents** - Selective loading based on page type
1331
-
1332
- ```javascript
1333
- output(`
1334
- 🔄 Generating pattern files...
1335
- `);
1336
-
1337
- // Create patterns directory
1338
- mkdir('design-system/patterns');
1339
-
1340
- // ========== 1. buttons.md ==========
1341
- const buttonsPattern = `# Button Patterns
1342
-
1343
- > **Source:** ${selectedStyle.site} | **Style:** ${selectedStyle.style}
1344
- > **Load when:** Any UI page
1345
-
1346
- ## Primary Button
1347
- \`\`\`tsx
1348
- <button className="
1349
- bg-primary text-primary-foreground
1350
- px-4 py-2 rounded-lg
1351
- font-medium
1352
- ${tokensData.animations.component_animations.button_hover === 'scale + shadow'
1353
- ? 'hover:scale-105 hover:shadow-md'
1354
- : 'hover:bg-primary/90'}
1355
- transition-all duration-200
1356
- focus:outline-none focus:ring-2 focus:ring-primary/50
1357
- disabled:opacity-50 disabled:cursor-not-allowed
1358
- ">
1359
- Button Text
1360
- </button>
1361
- \`\`\`
1362
-
1363
- ## Secondary Button
1364
- \`\`\`tsx
1365
- <button className="
1366
- bg-secondary text-secondary-foreground
1367
- px-4 py-2 rounded-lg
1368
- font-medium
1369
- hover:bg-secondary/80
1370
- transition-all duration-200
1371
- ">
1372
- Secondary
1373
- </button>
1374
- \`\`\`
1375
-
1376
- ## Ghost Button
1377
- \`\`\`tsx
1378
- <button className="
1379
- bg-transparent text-foreground
1380
- px-4 py-2 rounded-lg
1381
- font-medium
1382
- hover:bg-muted
1383
- transition-all duration-200
1384
- ">
1385
- Ghost
1386
- </button>
1387
- \`\`\`
1388
-
1389
- ## Outline Button
1390
- \`\`\`tsx
1391
- <button className="
1392
- bg-transparent text-primary
1393
- border border-primary
1394
- px-4 py-2 rounded-lg
1395
- font-medium
1396
- hover:bg-primary hover:text-primary-foreground
1397
- transition-all duration-200
1398
- ">
1399
- Outline
1400
- </button>
1401
- \`\`\`
1402
-
1403
- ## Icon Button
1404
- \`\`\`tsx
1405
- <button className="
1406
- p-2 rounded-lg
1407
- hover:bg-muted
1408
- transition-all duration-200
1409
- ">
1410
- <Icon className="w-5 h-5" />
1411
- </button>
1412
- \`\`\`
1413
-
1414
- ## Button Sizes
1415
- \`\`\`tsx
1416
- // Small
1417
- className="px-3 py-1.5 text-sm rounded-md"
1418
-
1419
- // Medium (default)
1420
- className="px-4 py-2 text-base rounded-lg"
1421
-
1422
- // Large
1423
- className="px-6 py-3 text-lg rounded-lg"
1424
- \`\`\`
1425
- `;
1426
-
1427
- Write('design-system/patterns/buttons.md', buttonsPattern);
1428
-
1429
- // ========== 2. scroll-animations.md ==========
1430
- const scrollAnimationsPattern = `# Scroll Animation Patterns
1431
-
1432
- > **Source:** ${selectedStyle.site} | **Style:** ${selectedStyle.style}
1433
- > **Load when:** Landing pages, marketing pages
1434
- > **Libraries:** ${tokensData.animations.libraries.map(l => l.name).join(', ') || 'CSS/Tailwind'}
1435
-
1436
- ## Enabled Patterns
1437
- ${selectedAnimations.length > 0 ? selectedAnimations.map(a => `- ${a}`).join('\n') : '- No scroll animations selected'}
1438
-
1439
- ---
1440
-
1441
- ## Fade In on Scroll (CSS)
1442
- \`\`\`tsx
1443
- // Add to component
1444
- const [isVisible, setIsVisible] = useState(false);
1445
- const ref = useRef(null);
1446
-
1447
- useEffect(() => {
1448
- const observer = new IntersectionObserver(
1449
- ([entry]) => setIsVisible(entry.isIntersecting),
1450
- { threshold: 0.1 }
1451
- );
1452
- if (ref.current) observer.observe(ref.current);
1453
- return () => observer.disconnect();
1454
- }, []);
1455
-
1456
- return (
1457
- <div
1458
- ref={ref}
1459
- className={\`
1460
- transition-all duration-700
1461
- \${isVisible ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-8'}
1462
- \`}
1463
- >
1464
- {children}
1465
- </div>
1466
- );
1467
- \`\`\`
1468
-
1469
- ## Stacking Cards (GSAP ScrollTrigger)
1470
- \`\`\`tsx
1471
- // Requires: npm install gsap
1472
-
1473
- import { gsap } from 'gsap';
1474
- import { ScrollTrigger } from 'gsap/ScrollTrigger';
1475
-
1476
- gsap.registerPlugin(ScrollTrigger);
1477
-
1478
- useEffect(() => {
1479
- const cards = gsap.utils.toArray('.stacking-card');
1480
-
1481
- cards.forEach((card, i) => {
1482
- gsap.to(card, {
1483
- scrollTrigger: {
1484
- trigger: card,
1485
- start: 'top 80%',
1486
- end: 'top 20%',
1487
- scrub: true,
1488
- },
1489
- y: -50 * i,
1490
- scale: 1 - (0.05 * i),
1491
- opacity: 1 - (0.1 * i),
1492
- });
1493
- });
1494
- }, []);
1495
-
1496
- // JSX
1497
- <div className="stacking-card bg-card p-6 rounded-xl shadow-md sticky top-20">
1498
- Card Content
1499
- </div>
1500
- \`\`\`
1501
-
1502
- ## Parallax Section
1503
- \`\`\`tsx
1504
- // CSS approach
1505
- <div className="relative overflow-hidden">
1506
- <div
1507
- className="absolute inset-0 bg-cover bg-center"
1508
- style={{
1509
- backgroundImage: 'url(/hero-bg.jpg)',
1510
- transform: 'translateY(var(--parallax-offset, 0))',
1511
- }}
1512
- />
1513
- <div className="relative z-10 py-24">
1514
- Content here
1515
- </div>
1516
- </div>
1517
-
1518
- // Update --parallax-offset on scroll
1519
- useEffect(() => {
1520
- const handleScroll = () => {
1521
- const offset = window.scrollY * 0.5;
1522
- document.documentElement.style.setProperty('--parallax-offset', \`\${offset}px\`);
1523
- };
1524
- window.addEventListener('scroll', handleScroll);
1525
- return () => window.removeEventListener('scroll', handleScroll);
1526
- }, []);
1527
- \`\`\`
1528
-
1529
- ## Slide In from Side
1530
- \`\`\`tsx
1531
- // Left
1532
- className="animate-slide-in-left"
1533
- // CSS: @keyframes slide-in-left { from { transform: translateX(-100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
1534
-
1535
- // Right
1536
- className="animate-slide-in-right"
1537
- // CSS: @keyframes slide-in-right { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
1538
- \`\`\`
1539
- `;
1540
-
1541
- Write('design-system/patterns/scroll-animations.md', scrollAnimationsPattern);
1542
-
1543
- // ========== 3. decorations.md ==========
1544
- const decorationsPattern = `# Decorative Elements
1545
-
1546
- > **Theme:** ${selectedTheme.name}
1547
- > **Load when:** Landing pages, marketing pages (NOT dashboards)
1548
-
1549
- ## Theme Direction
1550
-
1551
- ### ✅ USE These Elements
1552
- ${selectedTheme.decorative_elements.map(e => `- ${e}`).join('\n')}
1553
-
1554
- ### ❌ AVOID These Elements
1555
- ${selectedTheme.avoid_elements.length > 0 ? selectedTheme.avoid_elements.map(e => `- ${e}`).join('\n') : '- (none specified)'}
1556
-
1557
- ### 🎯 Suggested Icons (Lucide)
1558
- ${selectedTheme.icons_suggestion?.join(', ') || 'Default Lucide icons'}
1559
-
1560
- ---
1561
-
1562
- ## Gradient Background
1563
- \`\`\`tsx
1564
- // Subtle gradient overlay
1565
- <div className="
1566
- absolute inset-0 -z-10
1567
- bg-gradient-to-br from-primary/5 via-transparent to-accent/5
1568
- "/>
1569
-
1570
- // Mesh gradient (hero sections)
1571
- <div className="
1572
- absolute inset-0 -z-10
1573
- bg-[radial-gradient(ellipse_80%_80%_at_50%_-20%,rgba(var(--primary),0.3),transparent)]
1574
- "/>
1575
- \`\`\`
1576
-
1577
- ## Blob Shapes
1578
- \`\`\`tsx
1579
- // CSS blob
1580
- <div className="
1581
- absolute -top-20 -right-20 w-96 h-96
1582
- bg-primary/10 rounded-full blur-3xl
1583
- animate-blob
1584
- "/>
1585
-
1586
- // CSS for animation
1587
- // @keyframes blob {
1588
- // 0%, 100% { transform: translate(0, 0) scale(1); }
1589
- // 33% { transform: translate(30px, -50px) scale(1.1); }
1590
- // 66% { transform: translate(-20px, 20px) scale(0.9); }
1591
- // }
1592
- \`\`\`
1593
-
1594
- ## Grid Pattern
1595
- \`\`\`tsx
1596
- // Dot grid background
1597
- <div className="
1598
- absolute inset-0 -z-10
1599
- bg-[radial-gradient(#e5e7eb_1px,transparent_1px)]
1600
- [background-size:16px_16px]
1601
- "/>
1602
-
1603
- // Line grid
1604
- <div className="
1605
- absolute inset-0 -z-10
1606
- bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)]
1607
- [background-size:24px_24px]
1608
- "/>
1609
- \`\`\`
1610
-
1611
- ## Floating Elements
1612
- \`\`\`tsx
1613
- // Floating icons (for theme: ${selectedTheme.name})
1614
- <div className="absolute top-10 left-10 animate-float opacity-20">
1615
- <IconFromTheme className="w-12 h-12 text-primary" />
1616
- </div>
1617
-
1618
- // CSS
1619
- // @keyframes float {
1620
- // 0%, 100% { transform: translateY(0); }
1621
- // 50% { transform: translateY(-20px); }
1622
- // }
1623
- \`\`\`
1624
-
1625
- ## Dividers & Separators
1626
- \`\`\`tsx
1627
- // Wave divider
1628
- <svg className="w-full h-16" viewBox="0 0 1200 120" preserveAspectRatio="none">
1629
- <path d="M0,0V46.29c47.79,22.2,103.59,32.17,158,28,70.36-5.37,136.33-33.31,206.8-37.5C438.64,32.43,512.34,53.67,583,72.05c69.27,18,138.3,24.88,209.4,13.08,36.15-6,69.85-17.84,104.45-29.34C989.49,25,1113-14.29,1200,52.47V0Z" fill="currentColor" className="text-muted/30"/>
1630
- </svg>
1631
-
1632
- // Gradient line
1633
- <div className="h-px bg-gradient-to-r from-transparent via-border to-transparent" />
1634
- \`\`\`
1635
- `;
1636
-
1637
- Write('design-system/patterns/decorations.md', decorationsPattern);
1638
-
1639
- // ========== 4. cards.md ==========
1640
- const cardsPattern = `# Card Patterns
1641
-
1642
- > **Source:** ${selectedStyle.site} | **Style:** ${selectedStyle.style}
1643
- > **Load when:** Any UI page
1644
-
1645
- ## Default Card
1646
- \`\`\`tsx
1647
- <div className="
1648
- bg-card text-card-foreground
1649
- rounded-xl border shadow-md
1650
- p-6
1651
- ">
1652
- <h3 className="text-xl font-semibold mb-2">Card Title</h3>
1653
- <p className="text-muted-foreground">Card content goes here.</p>
1654
- </div>
1655
- \`\`\`
1656
-
1657
- ## Interactive Card (with hover)
1658
- \`\`\`tsx
1659
- <div className="
1660
- bg-card text-card-foreground
1661
- rounded-xl border shadow-md
1662
- p-6
1663
- ${tokensData.animations.component_animations.card_hover === 'translateY + shadow'
1664
- ? 'hover:-translate-y-1 hover:shadow-lg'
1665
- : 'hover:border-primary/50'}
1666
- transition-all duration-200
1667
- cursor-pointer
1668
- ">
1669
- <h3 className="text-xl font-semibold mb-2">Interactive Card</h3>
1670
- <p className="text-muted-foreground">Hover me!</p>
1671
- </div>
1672
- \`\`\`
1673
-
1674
- ## Feature Card
1675
- \`\`\`tsx
1676
- <div className="
1677
- bg-card text-card-foreground
1678
- rounded-xl border shadow-md
1679
- p-6
1680
- hover:-translate-y-1 hover:shadow-lg
1681
- transition-all duration-200
1682
- ">
1683
- <div className="w-12 h-12 rounded-lg bg-primary/10 flex items-center justify-center mb-4">
1684
- <Icon className="w-6 h-6 text-primary" />
1685
- </div>
1686
- <h3 className="text-lg font-semibold mb-2">Feature Title</h3>
1687
- <p className="text-muted-foreground text-sm">
1688
- Feature description goes here.
1689
- </p>
1690
- </div>
1691
- \`\`\`
1692
-
1693
- ## Pricing Card
1694
- \`\`\`tsx
1695
- <div className="
1696
- bg-card text-card-foreground
1697
- rounded-xl border shadow-md
1698
- p-8
1699
- relative overflow-hidden
1700
- ">
1701
- {/* Popular badge */}
1702
- <div className="absolute top-4 right-4">
1703
- <span className="bg-primary text-primary-foreground px-3 py-1 rounded-full text-xs font-medium">
1704
- Popular
1705
- </span>
1706
- </div>
1707
-
1708
- <h3 className="text-xl font-bold mb-2">Pro Plan</h3>
1709
- <div className="text-4xl font-bold mb-4">
1710
- $29<span className="text-lg text-muted-foreground">/mo</span>
1711
- </div>
1712
-
1713
- <ul className="space-y-3 mb-6">
1714
- <li className="flex items-center gap-2">
1715
- <CheckIcon className="w-5 h-5 text-primary" />
1716
- <span>Feature 1</span>
1717
- </li>
1718
- {/* ... more features */}
1719
- </ul>
1720
-
1721
- <button className="w-full bg-primary text-primary-foreground py-2 rounded-lg">
1722
- Get Started
1723
- </button>
1724
- </div>
1725
- \`\`\`
1726
-
1727
- ## Testimonial Card
1728
- \`\`\`tsx
1729
- <div className="
1730
- bg-card text-card-foreground
1731
- rounded-xl border shadow-md
1732
- p-6
1733
- ">
1734
- <div className="flex items-center gap-4 mb-4">
1735
- <img src="/avatar.jpg" className="w-12 h-12 rounded-full" />
1736
- <div>
1737
- <h4 className="font-semibold">John Doe</h4>
1738
- <p className="text-sm text-muted-foreground">CEO, Company</p>
1739
- </div>
1740
- </div>
1741
- <p className="text-muted-foreground italic">
1742
- "This product is amazing! It has transformed how we work."
1743
- </p>
1744
- </div>
1745
- \`\`\`
1746
- `;
1747
-
1748
- Write('design-system/patterns/cards.md', cardsPattern);
1749
-
1750
- // ========== 5. forms.md ==========
1751
- const formsPattern = `# Form Patterns
1752
-
1753
- > **Source:** ${selectedStyle.site} | **Style:** ${selectedStyle.style}
1754
- > **Load when:** Auth pages, settings, any form UI
1755
-
1756
- ## Input Field
1757
- \`\`\`tsx
1758
- <div className="space-y-2">
1759
- <label className="text-sm font-medium text-foreground">
1760
- Email Address
1761
- </label>
1762
- <input
1763
- type="email"
1764
- placeholder="you@example.com"
1765
- className="
1766
- w-full px-4 py-2
1767
- bg-background text-foreground
1768
- border rounded-md
1769
- focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary
1770
- placeholder:text-muted-foreground
1771
- transition-all duration-200
1772
- "
1773
- />
1774
- <p className="text-sm text-muted-foreground">
1775
- We'll never share your email.
1776
- </p>
1777
- </div>
1778
- \`\`\`
1779
-
1780
- ## Input with Error
1781
- \`\`\`tsx
1782
- <div className="space-y-2">
1783
- <label className="text-sm font-medium text-foreground">
1784
- Password
1785
- </label>
1786
- <input
1787
- type="password"
1788
- className="
1789
- w-full px-4 py-2
1790
- bg-background text-foreground
1791
- border border-error rounded-md
1792
- focus:outline-none focus:ring-2 focus:ring-error/50
1793
- "
1794
- />
1795
- <p className="text-sm text-error">
1796
- Password must be at least 8 characters.
1797
- </p>
1798
- </div>
1799
- \`\`\`
1800
-
1801
- ## Select Field
1802
- \`\`\`tsx
1803
- <div className="space-y-2">
1804
- <label className="text-sm font-medium text-foreground">
1805
- Country
1806
- </label>
1807
- <select className="
1808
- w-full px-4 py-2
1809
- bg-background text-foreground
1810
- border rounded-md
1811
- focus:outline-none focus:ring-2 focus:ring-primary/50
1812
- ">
1813
- <option value="">Select country</option>
1814
- <option value="th">Thailand</option>
1815
- <option value="us">United States</option>
1816
- </select>
1817
- </div>
1818
- \`\`\`
1819
-
1820
- ## Checkbox
1821
- \`\`\`tsx
1822
- <label className="flex items-center gap-2 cursor-pointer">
1823
- <input
1824
- type="checkbox"
1825
- className="
1826
- w-4 h-4 rounded
1827
- border border-border
1828
- text-primary
1829
- focus:ring-2 focus:ring-primary/50
1830
- "
1831
- />
1832
- <span className="text-sm text-foreground">
1833
- I agree to the terms and conditions
1834
- </span>
1835
- </label>
1836
- \`\`\`
1837
-
1838
- ## Form Layout
1839
- \`\`\`tsx
1840
- <form className="space-y-6 max-w-md mx-auto">
1841
- {/* Form fields */}
1842
-
1843
- <button
1844
- type="submit"
1845
- className="
1846
- w-full bg-primary text-primary-foreground
1847
- py-2 rounded-lg font-medium
1848
- hover:bg-primary/90
1849
- transition-all duration-200
1850
- "
1851
- >
1852
- Submit
1853
- </button>
1854
- </form>
1855
- \`\`\`
1856
- `;
1857
-
1858
- Write('design-system/patterns/forms.md', formsPattern);
1859
-
1860
- output(`
1861
1121
  ✅ Pattern files generated:
1862
1122
  - design-system/patterns/buttons.md
1863
1123
  - design-system/patterns/scroll-animations.md
1864
1124
  - design-system/patterns/decorations.md
1865
1125
  - design-system/patterns/cards.md
1866
1126
  - design-system/patterns/forms.md
1867
- `);
1868
1127
  ```
1869
1128
 
1129
+ → Continue to STEP 5.7
1130
+
1870
1131
  ---
1871
1132
 
1872
1133
  ## STEP 5.7: Generate Lean README.md (Human-Readable)
1873
1134
 
1874
1135
  > **Human-readable guide** - No code, just descriptions and visuals
1875
1136
 
1876
- ```javascript
1877
- output(`
1878
- 🔄 Generating lean README.md (human-readable)...
1879
- `);
1880
-
1881
- const styleGuideMD = `# ${selectedStyle.style} Design System
1882
-
1883
- > **Style:** ${selectedStyle.style}
1884
- > **Theme:** ${selectedTheme.name}
1885
- > **Generated:** ${new Date().toISOString().split('T')[0]}
1886
- > **Sources:** ${Object.keys(extractedData).join(', ')}
1887
-
1888
- ---
1889
-
1890
- ## 1. Overview
1891
-
1892
- This design system follows **${selectedStyle.style}** aesthetics with a **${selectedTheme.name}** theme.
1893
-
1894
- ### Feel
1895
- ${selectedStyle.feel}
1896
-
1897
- ### Characteristics
1898
- ${selectedStyle.characteristics.map(c => `- ${c}`).join('\n')}
1899
-
1900
- ---
1901
-
1902
- ## 2. Color Palette
1903
-
1904
- ### Primary Color
1905
- - **Color:** ${tokensData.colors.primary.DEFAULT}
1906
- - **Use for:** CTAs, links, accents, interactive elements
1907
- - **Feel:** ${selectedStyle.feel}
1908
-
1909
- ### Secondary Color
1910
- - **Color:** ${tokensData.colors.secondary.DEFAULT}
1911
- - **Use for:** Secondary actions, less prominent elements
1912
-
1913
- ### Background Colors
1914
- - **Main:** ${tokensData.colors.background.DEFAULT} (white)
1915
- - **Muted:** ${tokensData.colors.background.muted} (subtle sections)
1916
- - **Subtle:** ${tokensData.colors.background.subtle} (alternating sections)
1917
-
1918
- ### Text Colors
1919
- - **Primary text:** ${tokensData.colors.foreground.DEFAULT}
1920
- - **Muted text:** ${tokensData.colors.foreground.muted}
1921
- - **Subtle text:** ${tokensData.colors.foreground.subtle}
1922
-
1923
- ### Semantic Colors
1924
- - **Success:** ${tokensData.colors.semantic.success} (green)
1925
- - **Warning:** ${tokensData.colors.semantic.warning} (amber)
1926
- - **Error:** ${tokensData.colors.semantic.error} (red)
1927
- - **Info:** ${tokensData.colors.semantic.info} (blue)
1928
-
1929
- ---
1930
-
1931
- ## 3. Typography
1137
+ ### STEP 5.7.1: Display Progress Message
1932
1138
 
1933
- ### Font Family
1934
- - **Primary:** ${tokensData.typography.font_family.sans}
1935
- - **Monospace:** ${tokensData.typography.font_family.mono}
1936
-
1937
- ### Heading Sizes
1938
- - **H1:** 48px bold - Hero headlines
1939
- - **H2:** 36px bold - Section titles
1940
- - **H3:** 30px semibold - Subsection titles
1941
- - **H4:** 24px semibold - Card titles
1942
- - **H5:** 20px medium - Feature titles
1943
- - **H6:** 18px medium - Small titles
1944
-
1945
- ### Body Text
1946
- - **Large:** 18px - Feature descriptions
1947
- - **Base:** 16px - Body text
1948
- - **Small:** 14px - Captions, labels
1949
- - **Extra small:** 12px - Badges, tags
1950
-
1951
- ---
1952
-
1953
- ## 4. Spacing System
1954
-
1955
- ### Base Unit
1956
- ${tokensData.spacing.grid_base} grid system
1957
-
1958
- ### Scale
1959
- ${tokensData.spacing.scale.map(s => `- ${s}px`).join('\n')}
1960
-
1961
- ### Common Patterns
1962
- - **Component padding:** 16px or 24px
1963
- - **Section gap:** 32px or 48px
1964
- - **Layout margin:** 64px or 96px
1965
-
1966
- ---
1967
-
1968
- ## 5. Shadows & Elevation
1969
-
1970
- ### Elevation Levels
1971
- - **Level 0:** No shadow (flat elements)
1972
- - **Level 1:** Subtle shadow (buttons on hover)
1973
- - **Level 2:** Medium shadow (cards)
1974
- - **Level 3:** Large shadow (dropdowns)
1975
- - **Level 4:** Extra large shadow (modals)
1976
-
1977
- ### Usage
1978
- - **Cards:** Medium shadow
1979
- - **Dropdowns:** Large shadow
1980
- - **Modals:** Extra large shadow
1981
- - **Button hover:** Subtle shadow
1982
-
1983
- ---
1984
-
1985
- ## 6. Border Radius
1986
-
1987
- ### Values
1988
- ${tokensData.borders.radius.map(r => `- ${r}`).join('\n')}
1989
-
1990
- ### Usage
1991
- - **Inputs:** Medium radius (8px)
1992
- - **Buttons:** Large radius (12px)
1993
- - **Cards:** Extra large radius (16px)
1994
- - **Avatars:** Full radius (circle)
1995
-
1996
- ---
1139
+ Display progress message:
1140
+ ```
1141
+ 🔄 Generating lean README.md (human-readable)...
1142
+ ```
1997
1143
 
1998
- ## 7. Theme: ${selectedTheme.name}
1144
+ ### STEP 5.7.2: Build README Content
1999
1145
 
2000
- ### Description
2001
- ${selectedTheme.description}
1146
+ Build a markdown document with these 11 sections:
2002
1147
 
2003
- ### Feeling
2004
- ${selectedTheme.feeling || selectedTheme.description}
1148
+ **Header:**
1149
+ - Title: "[selectedStyle.style] Design System"
1150
+ - Metadata: Style, Theme, Generated date, Sources
2005
1151
 
2006
- ### Decorative Elements to USE
2007
- ${selectedTheme.decorative_elements.map(e => `- ${e}`).join('\n')}
1152
+ **Section 1: Overview**
1153
+ - Description of design system (style + theme)
1154
+ - Feel: selectedStyle.feel
1155
+ - Characteristics: List from selectedStyle.characteristics
2008
1156
 
2009
- ### Elements to AVOID
2010
- ${selectedTheme.avoid_elements.length > 0 ? selectedTheme.avoid_elements.map(e => `- ❌ ${e}`).join('\n') : '- (none specified)'}
1157
+ **Section 2: Color Palette**
1158
+ - Primary Color (value, usage, feel)
1159
+ - Secondary Color (value, usage)
1160
+ - Background Colors (DEFAULT, muted, subtle)
1161
+ - Text Colors (DEFAULT, muted, subtle)
1162
+ - Semantic Colors (success, warning, error, info)
2011
1163
 
2012
- ### Suggested Icons
2013
- ${selectedTheme.icons_suggestion?.join(', ') || 'Lucide icons'}
1164
+ **Section 3: Typography**
1165
+ - Font Family (sans, monospace)
1166
+ - Heading Sizes (H1-H6 with px sizes and weights)
1167
+ - Body Text (large, base, small, extra small)
2014
1168
 
2015
- ---
1169
+ **Section 4: Spacing System**
1170
+ - Base Unit: tokensData.spacing.grid_base
1171
+ - Scale: List from tokensData.spacing.scale
1172
+ - Common Patterns (component padding, section gap, layout margin)
2016
1173
 
2017
- ## 8. Animations
1174
+ **Section 5: Shadows & Elevation**
1175
+ - Elevation Levels (0-4)
1176
+ - Usage guide for each level
2018
1177
 
2019
- ### Enabled
2020
- ${tokensData.animations.enabled ? 'Yes' : 'No'}
1178
+ **Section 6: Border Radius**
1179
+ - Values: List from tokensData.borders.radius
1180
+ - Usage guide (inputs, buttons, cards, avatars)
2021
1181
 
2022
- ### Libraries
2023
- ${tokensData.animations.libraries.map(l => `- ${l.name}`).join('\n') || '- CSS/Tailwind only'}
1182
+ **Section 7: Theme**
1183
+ - Theme name: selectedTheme.name
1184
+ - Description and feeling
1185
+ - Decorative Elements to USE (list)
1186
+ - Elements to AVOID (list or "none specified")
1187
+ - Suggested Icons
2024
1188
 
2025
- ### Selected Patterns
2026
- ${selectedAnimations.length > 0 ? selectedAnimations.map(a => `- ${a}`).join('\n') : '- No scroll animations'}
1189
+ **Section 8: Animations**
1190
+ - Enabled status (Yes/No)
1191
+ - Libraries list or "CSS/Tailwind only"
1192
+ - Selected Patterns list or "No scroll animations"
1193
+ - Component Animations (button hover, card hover, input focus)
1194
+ - Timing (fast, normal, slow)
2027
1195
 
2028
- ### Component Animations
2029
- - **Button hover:** ${tokensData.animations.component_animations.button_hover}
2030
- - **Card hover:** ${tokensData.animations.component_animations.card_hover}
2031
- - **Input focus:** ${tokensData.animations.component_animations.input_focus}
1196
+ **Section 9: Component Library**
1197
+ - Recommended: tokensData.component_library.name
1198
+ - Common Components list
2032
1199
 
2033
- ### Timing
2034
- - **Fast:** 150ms (micro-interactions)
2035
- - **Normal:** 200ms (most transitions)
2036
- - **Slow:** 300ms (modals, page transitions)
1200
+ **Section 10: Code Patterns**
1201
+ - Reference links to all 5 pattern files
2037
1202
 
2038
- ---
1203
+ **Section 11: Critical Rules**
1204
+ - Colors rules (NO hardcoded hex, USE tokens)
1205
+ - Spacing rules (NO arbitrary values, USE scale)
1206
+ - Consistency rules (NO mixing, USE consistent patterns)
2039
1207
 
2040
- ## 9. Component Library
1208
+ **Footer:**
1209
+ - "Generated by /designsetup v2.0.0"
1210
+ - "Sources: [list of extracted sites]"
2041
1211
 
2042
- ### Recommended
2043
- ${tokensData.component_library.name}
1212
+ ### STEP 5.7.3: Write README File
2044
1213
 
2045
- ### Common Components
2046
- ${tokensData.component_library.common_components.map(c => `- ${c}`).join('\n')}
1214
+ Write the markdown content to `design-system/README.md`
2047
1215
 
2048
- ---
1216
+ ### STEP 5.7.4: Display Confirmation
2049
1217
 
2050
- ## 10. Code Patterns
1218
+ Display confirmation message:
1219
+ ```
1220
+ ✅ README.md generated (lean, human-readable, ~100 lines)
1221
+ ```
2051
1222
 
2052
- **For code examples, see:**
2053
- - \`design-system/patterns/buttons.md\`
2054
- - \`design-system/patterns/cards.md\`
2055
- - \`design-system/patterns/forms.md\`
2056
- - \`design-system/patterns/scroll-animations.md\`
2057
- - \`design-system/patterns/decorations.md\`
1223
+ Continue to STEP 6
2058
1224
 
2059
1225
  ---
2060
1226
 
2061
- ## 11. Critical Rules
2062
-
2063
- ### Colors
2064
- - ❌ NO hardcoded hex values
2065
- - ✅ USE theme tokens (bg-primary, text-foreground)
2066
-
2067
- ### Spacing
2068
- - ❌ NO arbitrary values (p-5, gap-7)
2069
- - ✅ USE spacing scale (p-4, p-6, gap-8)
2070
-
2071
- ### Consistency
2072
- - ❌ NO mixing patterns
2073
- - ✅ USE consistent patterns from tokens
2074
-
2075
- ---
1227
+ ## STEP 6: Final Report
2076
1228
 
2077
- *Generated by /designsetup v2.0.0*
2078
- *Sources: ${Object.keys(extractedData).join(', ')}*
2079
- `;
1229
+ Display a comprehensive final report with these sections:
2080
1230
 
2081
- Write('design-system/README.md', styleGuideMD);
2082
- output(`✅ README.md generated (lean, human-readable, ~100 lines)`);
1231
+ **Header:**
2083
1232
  ```
2084
-
2085
- ---
2086
-
2087
- ## STEP 6: Final Report
2088
-
2089
- ```javascript
2090
- output(`
2091
1233
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2092
1234
  ✅ Design Setup Complete!
2093
1235
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1236
+ ```
2094
1237
 
2095
- 📊 Summary:
2096
- Style: ${selectedStyle.style} (from ${selectedStyle.site})
2097
- Theme: ${selectedTheme.name}
2098
- Sources: ${Object.keys(extractedData).join(', ')}
2099
- Animations: ${selectedAnimations.length} patterns enabled
2100
-
2101
- 🎨 Style Characteristics:
2102
- ${selectedStyle.characteristics.slice(0, 4).map(c => ` • ${c}`).join('\n')}
2103
-
2104
- 🎭 Theme Direction:
2105
- USE: ${selectedTheme.decorative_elements.slice(0, 3).join(', ')}
2106
- AVOID: ${selectedTheme.avoid_elements.slice(0, 2).join(', ') || '(none)'}
2107
-
2108
- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2109
-
2110
- 📦 Files Created:
2111
-
2112
- 🤖 FOR AGENTS (merged data + psychology):
2113
- design-system/data.yaml (~300 lines)
2114
- design-system/patterns/buttons.md
2115
- design-system/patterns/cards.md
2116
- ✓ design-system/patterns/forms.md
2117
- design-system/patterns/scroll-animations.md
2118
- design-system/patterns/decorations.md
2119
-
2120
- 👤 FOR HUMANS (summary):
2121
- ✓ design-system/README.md (~100 lines)
2122
-
1238
+ **Summary Section:**
1239
+ - Style: [selectedStyle.style] (from [selectedStyle.site])
1240
+ - Theme: [selectedTheme.name]
1241
+ - Sources: [list of extracted sites]
1242
+ - Animations: [count] patterns enabled
1243
+
1244
+ **Style Characteristics:**
1245
+ - List first 4 characteristics from selectedStyle.characteristics
1246
+
1247
+ **Theme Direction:**
1248
+ - USE: First 3 elements from selectedTheme.decorative_elements
1249
+ - AVOID: First 2 elements from selectedTheme.avoid_elements or "(none)"
1250
+
1251
+ **Files Created:**
1252
+ - FOR AGENTS section:
1253
+ - design-system/data.yaml (~300 lines)
1254
+ - design-system/patterns/buttons.md
1255
+ - design-system/patterns/cards.md
1256
+ - design-system/patterns/forms.md
1257
+ - design-system/patterns/scroll-animations.md
1258
+ - design-system/patterns/decorations.md
1259
+
1260
+ - FOR HUMANS section:
1261
+ - design-system/README.md (~100 lines)
1262
+
1263
+ **Next Steps:**
1264
+ 1. Review generated files (commands provided)
1265
+ 2. Plan your pages with /pageplan
1266
+ 3. Setup & develop with /csetup and /cdev
1267
+
1268
+ **How It Works:**
1269
+ - Explain /pageplan reads data.yaml and auto-detects page type
1270
+ - Explain uxui-frontend agent reads data.yaml and selective patterns
1271
+ - Mention content includes Psychology, Target Audience, Why It Works
1272
+
1273
+ **Footer:**
1274
+ ```
2123
1275
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1276
+ ```
2124
1277
 
2125
- 🚀 Next Steps:
2126
-
2127
- 1. Review generated files:
2128
- cat design-system/data.yaml | head -50
2129
- cat design-system/README.md
2130
-
2131
- 2. Plan your pages:
2132
- /pageplan @prd.md @project.md
2133
-
2134
- 3. Setup & develop:
2135
- /csetup feature-landing
2136
- /cdev feature-landing
2137
-
2138
- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1278
+ ---
2139
1279
 
2140
- 📖 How It Works:
1280
+ ## Helper: Generate data.yaml
2141
1281
 
2142
- /pageplan reads:
2143
- → data.yaml (style, theme, colors, animations, psychology)
2144
- → Auto-detects page type (landing/dashboard/auth)
2145
- → Loads patterns/*.md selectively
1282
+ This helper function generates the complete data.yaml file by merging psychology data from extracted sites with design tokens.
2146
1283
 
2147
- uxui-frontend agent reads:
2148
- data.yaml (tokens + psychology)
2149
- patterns/buttons.md (always)
2150
- patterns/cards.md (always)
2151
- → patterns/scroll-animations.md (landing pages only)
2152
- → patterns/decorations.md (landing pages only)
2153
- → patterns/forms.md (forms only)
1284
+ **Inputs:**
1285
+ - tokensData: Design tokens object built in STEP 5.5
1286
+ - extractedData: All extracted site data
1287
+ - selectedStyle: Selected style object from user choice
2154
1288
 
2155
- Content includes: Psychology, Target Audience, Why It Works ✨
1289
+ **Process:**
2156
1290
 
2157
- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2158
- `);
2159
- ```
1291
+ 1. Get psychology data from the selected site:
1292
+ - selectedSiteData = extractedData[selectedStyle.site]
1293
+ - psychology = selectedSiteData.psychology or empty object
1294
+
1295
+ 2. Build YAML content with 5 major sections:
1296
+
1297
+ **Section 1: Header Comments**
1298
+ - Generated by: /designsetup
1299
+ - Source: selectedStyle.site
1300
+ - Style: selectedStyle.style
1301
+
1302
+ **Section 2: Meta**
1303
+ - generated_at: Current ISO timestamp
1304
+ - source_site: selectedStyle.site
1305
+ - style: selectedStyle.style
1306
+ - theme: tokensData.theme.name or "default"
1307
+
1308
+ **Section 3: Psychology & Analysis**
1309
+ - style_classification: From psychology or selectedStyle.style
1310
+ - emotions_evoked: List of {emotion, reason} or "# Not available"
1311
+ - target_audience:
1312
+ - primary: {description, age_range, tech_savvy}
1313
+ - secondary: {description}
1314
+ - visual_principles: List of {name, description} or "# Not available"
1315
+ - why_it_works: List of strings or "# Not available"
1316
+ - design_philosophy: {core_belief, key_principles list} or "Not specified"
1317
+
1318
+ **Section 4: Design Tokens**
1319
+ - style: {detected, characteristics list, feel}
1320
+ - colors: {primary, secondary, background, foreground, muted, accent}
1321
+ - typography: {font_family, heading_font, weights array, sizes object}
1322
+ - spacing: {base, scale array}
1323
+ - border_radius: {sm, md, lg, full}
1324
+ - shadows: {sm, md, lg}
1325
+
1326
+ **Section 5: Animations**
1327
+ - durations: {fast, normal, slow}
1328
+ - easing: {default, bounce}
1329
+ - component_animations: {button_hover, card_hover}
1330
+ - scroll_animations: {enabled boolean, patterns array}
1331
+
1332
+ **Section 6: Theme Direction**
1333
+ - theme: {name, decorative_elements list, avoid_elements list}
1334
+
1335
+ **Output:** Returns the complete YAML content as a string
2160
1336
 
2161
1337
  ---
2162
1338
 
2163
- ## Helper: Generate data.yaml
2164
-
2165
- ```javascript
2166
- function generateDataYaml(tokensData, extractedData, selectedStyle) {
2167
- // Get psychology from the selected extracted site
2168
- const selectedSiteData = extractedData[selectedStyle.site];
2169
- const psychology = selectedSiteData?.psychology || {};
2170
-
2171
- return `# Design System Data
2172
- # Generated by: /designsetup
2173
- # Source: ${selectedStyle.site}
2174
- # Style: ${selectedStyle.style}
1339
+ ## Error Handling
2175
1340
 
2176
- meta:
2177
- generated_at: ${new Date().toISOString()}
2178
- source_site: ${selectedStyle.site}
2179
- style: ${selectedStyle.style}
2180
- theme: ${tokensData.theme?.name || 'default'}
2181
-
2182
- # ============================================
2183
- # PSYCHOLOGY & ANALYSIS
2184
- # ============================================
2185
-
2186
- psychology:
2187
- style_classification: ${psychology.style_classification || selectedStyle.style}
2188
-
2189
- emotions_evoked:
2190
- ${(psychology.emotions_evoked || []).map(e => ` - emotion: "${e.emotion}"
2191
- reason: "${e.reason}"`).join('\n') || ' # Not available'}
2192
-
2193
- target_audience:
2194
- primary:
2195
- description: "${psychology.target_audience?.primary?.description || 'Not specified'}"
2196
- age_range: "${psychology.target_audience?.primary?.age_range || 'mixed'}"
2197
- tech_savvy: ${psychology.target_audience?.primary?.tech_savvy || 'medium'}
2198
- secondary:
2199
- description: "${psychology.target_audience?.secondary?.description || 'Not specified'}"
2200
-
2201
- visual_principles:
2202
- ${(psychology.visual_principles || []).map(v => ` - name: "${v.name}"
2203
- description: "${v.description}"`).join('\n') || ' # Not available'}
2204
-
2205
- why_it_works:
2206
- ${(psychology.why_it_works || []).map(w => ` - "${w}"`).join('\n') || ' # Not available'}
2207
-
2208
- design_philosophy:
2209
- core_belief: "${psychology.design_philosophy?.core_belief || 'Not specified'}"
2210
- key_principles:
2211
- ${(psychology.design_philosophy?.key_principles || []).map(p => ` - "${p}"`).join('\n') || ' # Not available'}
2212
-
2213
- # ============================================
2214
- # DESIGN TOKENS
2215
- # ============================================
2216
-
2217
- style:
2218
- detected: ${tokensData.style.detected}
2219
- characteristics:
2220
- ${tokensData.style.characteristics.map(c => ` - "${c}"`).join('\n')}
2221
- feel: "${tokensData.style.feel}"
1341
+ Handle these error scenarios throughout the workflow:
2222
1342
 
2223
- colors:
2224
- primary: "${tokensData.colors.primary}"
2225
- secondary: "${tokensData.colors.secondary}"
2226
- background: "${tokensData.colors.background}"
2227
- foreground: "${tokensData.colors.foreground}"
2228
- muted: "${tokensData.colors.muted}"
2229
- accent: "${tokensData.colors.accent}"
1343
+ ### Error 1: No Extracted Data (STEP 0.1)
2230
1344
 
2231
- typography:
2232
- font_family: "${tokensData.typography.font_family}"
2233
- heading_font: "${tokensData.typography.heading_font}"
2234
- weights: [${tokensData.typography.weights.join(', ')}]
2235
- sizes:
2236
- h1: "${tokensData.typography.sizes.h1}"
2237
- h2: "${tokensData.typography.sizes.h2}"
2238
- h3: "${tokensData.typography.sizes.h3}"
2239
- body: "${tokensData.typography.sizes.body}"
2240
- small: "${tokensData.typography.sizes.small}"
1345
+ **When:** No design-system/extracted/*/data.yaml files found
2241
1346
 
2242
- spacing:
2243
- base: ${tokensData.spacing.base}
2244
- scale: [${tokensData.spacing.scale.join(', ')}]
1347
+ **Action:** Display error message and stop execution:
1348
+ ```
1349
+ No extracted data found
2245
1350
 
2246
- border_radius:
2247
- sm: "${tokensData.border_radius.sm}"
2248
- md: "${tokensData.border_radius.md}"
2249
- lg: "${tokensData.border_radius.lg}"
2250
- full: "${tokensData.border_radius.full}"
1351
+ Please extract at least 1 site:
1352
+ /extract https://airbnb.com
2251
1353
 
2252
- shadows:
2253
- sm: "${tokensData.shadows.sm}"
2254
- md: "${tokensData.shadows.md}"
2255
- lg: "${tokensData.shadows.lg}"
2256
-
2257
- # ============================================
2258
- # ANIMATIONS
2259
- # ============================================
2260
-
2261
- animations:
2262
- durations:
2263
- fast: "${tokensData.animations.durations.fast}"
2264
- normal: "${tokensData.animations.durations.normal}"
2265
- slow: "${tokensData.animations.durations.slow}"
2266
- easing:
2267
- default: "${tokensData.animations.easing.default}"
2268
- bounce: "${tokensData.animations.easing.bounce}"
2269
- component_animations:
2270
- button_hover: "${tokensData.animations.component_animations.button_hover}"
2271
- card_hover: "${tokensData.animations.component_animations.card_hover}"
2272
- scroll_animations:
2273
- enabled: ${tokensData.animations.scroll_animations.enabled}
2274
- patterns:
2275
- ${(tokensData.animations.scroll_animations.patterns || []).map(p => ` - "${p}"`).join('\n')}
2276
-
2277
- # ============================================
2278
- # THEME DIRECTION
2279
- # ============================================
2280
-
2281
- theme:
2282
- name: "${tokensData.theme?.name || 'default'}"
2283
- decorative_elements:
2284
- ${(tokensData.theme?.decorative_elements || []).map(d => ` - "${d}"`).join('\n')}
2285
- avoid_elements:
2286
- ${(tokensData.theme?.avoid_elements || []).map(a => ` - "${a}"`).join('\n')}
2287
- `;
2288
- }
1354
+ Then run: /designsetup @prd.md
2289
1355
  ```
2290
1356
 
2291
- ---
1357
+ ### Error 2: AI Analysis Fails (STEP 1.2, 2.3, etc.)
2292
1358
 
2293
- ## Error Handling
1359
+ **When:** LLM call fails during context analysis or style generation
2294
1360
 
2295
- ```javascript
2296
- // No extracted data
2297
- if (extractedDirs.length === 0) {
2298
- return error(`
2299
- ❌ No extracted data found
1361
+ **Action:** Catch error and display message with debugging guidance:
1362
+ ```
1363
+ AI analysis failed: [error.message]
2300
1364
 
2301
- Please extract at least 1 site:
2302
- /extract https://airbnb.com
1365
+ This may be due to:
1366
+ - Extracted data too large (try fewer sites)
1367
+ - API rate limit (wait and retry)
1368
+ - Invalid context files
2303
1369
 
2304
- Then run: /designsetup @prd.md
2305
- `);
2306
- }
1370
+ Retry or use --debug for details
1371
+ ```
2307
1372
 
2308
- // AI analysis fails
2309
- try {
2310
- const styleOptions = await LLM({ ... });
2311
- } catch (error) {
2312
- return error(`
2313
- ❌ AI analysis failed: ${error.message}
1373
+ ### Error 3: User Cancels (STEP 2.8)
2314
1374
 
2315
- This may be due to:
2316
- - Extracted data too large (try fewer sites)
2317
- - API rate limit (wait and retry)
2318
- - Invalid context files
1375
+ **When:** User selects "Cancel" option at max rounds or during confirmation
2319
1376
 
2320
- Retry or use --debug for details
2321
- `);
2322
- }
1377
+ **Action:** Display cancellation message and preserve data:
1378
+ ```
1379
+ ⚠️ Design setup cancelled
2323
1380
 
2324
- // User cancels
2325
- if (!userChoice) {
2326
- output(`
2327
- ⚠️ Design setup cancelled
1381
+ Your data is preserved:
1382
+ - Extracted: design-system/extracted/
1383
+ - Options: design-system/synthesis/options/
2328
1384
 
2329
- Your data is preserved:
2330
- - Extracted: design-system/extracted/
2331
- - Options: design-system/synthesis/options/
1385
+ Run /designsetup again when ready.
1386
+ ```
2332
1387
 
2333
- Run /designsetup again when ready.
2334
- `);
2335
- return;
2336
- }
1388
+ ### Error 4: Write Fails (STEP 5.6, 5.7)
2337
1389
 
2338
- // Write fails
2339
- try {
2340
- Write('design-system/README.md', styleGuideMD);
2341
- } catch (error) {
2342
- // Save backup
2343
- Write('/tmp/style-guide-backup.md', styleGuideMD);
1390
+ **When:** Unable to write to design-system/ directory
2344
1391
 
2345
- return error(`
2346
- Failed to write README.md
1392
+ **Action:**
1393
+ 1. Save backup to temporary location: /tmp/style-guide-backup.md
1394
+ 2. Display error message with backup location:
1395
+ ```
1396
+ ❌ Failed to write README.md
2347
1397
 
2348
- Check permissions: design-system/
1398
+ Check permissions: design-system/
2349
1399
 
2350
- Backup saved: /tmp/style-guide-backup.md
2351
- `);
2352
- }
1400
+ Backup saved: /tmp/style-guide-backup.md
2353
1401
  ```
2354
1402
 
2355
1403
  ---