flight-rules 0.15.3 → 0.15.6

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.
@@ -5,6 +5,20 @@ export declare function copyCommandsWithConflictHandling(sourceDir: string, dest
5
5
  copied: string[];
6
6
  skipped: string[];
7
7
  }>;
8
+ /**
9
+ * Copy skill files to a destination directory with conflict handling
10
+ */
11
+ export declare function copySkillsWithConflictHandling(sourceDir: string, destDir: string, skipPrompts?: boolean): Promise<{
12
+ copied: string[];
13
+ skipped: string[];
14
+ }>;
15
+ /**
16
+ * Setup skills for a given adapter directory
17
+ */
18
+ export declare function setupSkills(cwd: string, sourceSkillsDir: string, adapterSkillsDir: string, skipPrompts?: boolean): Promise<{
19
+ copied: string[];
20
+ skipped: string[];
21
+ }>;
8
22
  /**
9
23
  * Setup Cursor-specific directories and commands
10
24
  */
@@ -140,6 +140,68 @@ async function promptForConflict(filename, showBatchOptions) {
140
140
  }
141
141
  return action;
142
142
  }
143
+ /**
144
+ * Copy skill files to a destination directory with conflict handling
145
+ */
146
+ export async function copySkillsWithConflictHandling(sourceDir, destDir, skipPrompts = false) {
147
+ const copied = [];
148
+ const skipped = [];
149
+ if (!existsSync(sourceDir)) {
150
+ return { copied, skipped };
151
+ }
152
+ const files = readdirSync(sourceDir).filter(f => f.endsWith('.md'));
153
+ let batchAction = null;
154
+ for (const file of files) {
155
+ const srcPath = join(sourceDir, file);
156
+ const destPath = join(destDir, file);
157
+ if (existsSync(destPath)) {
158
+ if (skipPrompts) {
159
+ cpSync(srcPath, destPath);
160
+ copied.push(file);
161
+ continue;
162
+ }
163
+ if (batchAction === 'replace_all') {
164
+ cpSync(srcPath, destPath);
165
+ copied.push(file);
166
+ continue;
167
+ }
168
+ else if (batchAction === 'skip_all') {
169
+ skipped.push(file);
170
+ continue;
171
+ }
172
+ const action = await promptForConflict(file, files.length > 1);
173
+ if (action === 'replace_all') {
174
+ batchAction = 'replace_all';
175
+ cpSync(srcPath, destPath);
176
+ copied.push(file);
177
+ }
178
+ else if (action === 'skip_all') {
179
+ batchAction = 'skip_all';
180
+ skipped.push(file);
181
+ }
182
+ else if (action === 'replace') {
183
+ cpSync(srcPath, destPath);
184
+ copied.push(file);
185
+ }
186
+ else {
187
+ skipped.push(file);
188
+ }
189
+ }
190
+ else {
191
+ cpSync(srcPath, destPath);
192
+ copied.push(file);
193
+ }
194
+ }
195
+ return { copied, skipped };
196
+ }
197
+ /**
198
+ * Setup skills for a given adapter directory
199
+ */
200
+ export async function setupSkills(cwd, sourceSkillsDir, adapterSkillsDir, skipPrompts = false) {
201
+ ensureDir(join(cwd, adapterSkillsDir.split('/')[0])); // e.g., .claude
202
+ ensureDir(join(cwd, adapterSkillsDir));
203
+ return copySkillsWithConflictHandling(sourceSkillsDir, join(cwd, adapterSkillsDir), skipPrompts);
204
+ }
143
205
  /**
144
206
  * Setup Cursor-specific directories and commands
145
207
  */
@@ -240,8 +302,10 @@ export async function adapter(args) {
240
302
  }
241
303
  export async function generateAdapters(adapterNames, sourceCommandsDir, interactive = true) {
242
304
  const cwd = process.cwd();
305
+ const flightRulesDir = getFlightRulesDir(cwd);
243
306
  // Default to .flight-rules/commands if no source specified
244
- const commandsDir = sourceCommandsDir ?? join(getFlightRulesDir(cwd), 'commands');
307
+ const commandsDir = sourceCommandsDir ?? join(flightRulesDir, 'commands');
308
+ const skillsDir = join(flightRulesDir, 'skills');
245
309
  for (const name of adapterNames) {
246
310
  const config = ADAPTERS[name];
247
311
  if (!config)
@@ -278,7 +342,7 @@ export async function generateAdapters(adapterNames, sourceCommandsDir, interact
278
342
  p.log.success(`Created ${pc.cyan(config.filename)} for ${config.name}`);
279
343
  adapterFileWritten = true;
280
344
  }
281
- // For Cursor, also set up .cursor/commands/
345
+ // For Cursor, also set up .cursor/commands/ and .cursor/skills/
282
346
  if (name === 'cursor') {
283
347
  const skipPrompts = !interactive;
284
348
  const commandsDirExists = isCursorAdapterInstalled(cwd);
@@ -290,8 +354,18 @@ export async function generateAdapters(adapterNames, sourceCommandsDir, interact
290
354
  if (result.skipped.length > 0) {
291
355
  p.log.info(`Skipped ${result.skipped.length} existing command(s) in .cursor/commands/`);
292
356
  }
357
+ // Copy skills
358
+ if (existsSync(skillsDir)) {
359
+ const skillResult = await setupSkills(cwd, skillsDir, '.cursor/skills', skipPrompts);
360
+ if (skillResult.copied.length > 0) {
361
+ p.log.success(`${commandsDirExists ? 'Updated' : 'Created'} ${pc.cyan('.cursor/skills/')} with ${skillResult.copied.length} skill(s)`);
362
+ }
363
+ if (skillResult.skipped.length > 0) {
364
+ p.log.info(`Skipped ${skillResult.skipped.length} existing skill(s) in .cursor/skills/`);
365
+ }
366
+ }
293
367
  }
294
- // For Claude, also set up .claude/commands/
368
+ // For Claude, also set up .claude/commands/ and .claude/skills/
295
369
  if (name === 'claude') {
296
370
  const skipPrompts = !interactive;
297
371
  const commandsDirExists = isClaudeAdapterInstalled(cwd);
@@ -303,6 +377,16 @@ export async function generateAdapters(adapterNames, sourceCommandsDir, interact
303
377
  if (result.skipped.length > 0) {
304
378
  p.log.info(`Skipped ${result.skipped.length} existing command(s) in .claude/commands/`);
305
379
  }
380
+ // Copy skills
381
+ if (existsSync(skillsDir)) {
382
+ const skillResult = await setupSkills(cwd, skillsDir, '.claude/skills', skipPrompts);
383
+ if (skillResult.copied.length > 0) {
384
+ p.log.success(`${commandsDirExists ? 'Updated' : 'Created'} ${pc.cyan('.claude/skills/')} with ${skillResult.copied.length} skill(s)`);
385
+ }
386
+ if (skillResult.skipped.length > 0) {
387
+ p.log.info(`Skipped ${skillResult.skipped.length} existing skill(s) in .claude/skills/`);
388
+ }
389
+ }
306
390
  }
307
391
  }
308
392
  }
@@ -4,7 +4,7 @@ import { existsSync, cpSync } from 'fs';
4
4
  import { join } from 'path';
5
5
  import { isFlightRulesInstalled, fetchPayloadFromGitHub, copyFrameworkFilesFrom, ensureDir, getInstalledVersion, writeManifest, getCliVersion } from '../utils/files.js';
6
6
  import { isInteractive } from '../utils/interactive.js';
7
- import { isCursorAdapterInstalled, isClaudeAdapterInstalled, setupCursorCommands, setupClaudeCommands, } from './adapter.js';
7
+ import { isCursorAdapterInstalled, isClaudeAdapterInstalled, setupCursorCommands, setupClaudeCommands, setupSkills, } from './adapter.js';
8
8
  const DOC_FILES = [
9
9
  { src: 'prd.md', dest: 'prd.md' },
10
10
  { src: 'progress.md', dest: 'progress.md' },
@@ -148,21 +148,34 @@ export async function upgrade(version) {
148
148
  spinner.start('Upgrading adapters...');
149
149
  try {
150
150
  const sourceCommandsDir = join(fetched.payloadPath, 'commands');
151
- // Upgrade Cursor commands if installed
151
+ const sourceSkillsDir = join(fetched.payloadPath, 'skills');
152
+ // Upgrade Cursor commands and skills if installed
152
153
  if (cursorAdapterInstalled) {
153
154
  const result = await setupCursorCommands(cwd, sourceCommandsDir, true); // skipPrompts = true for upgrade
154
155
  if (result.copied.length > 0) {
155
156
  p.log.success(`Updated ${result.copied.length} command(s) in .cursor/commands/`);
156
157
  }
158
+ if (existsSync(sourceSkillsDir)) {
159
+ const skillResult = await setupSkills(cwd, sourceSkillsDir, '.cursor/skills', true);
160
+ if (skillResult.copied.length > 0) {
161
+ p.log.success(`Updated ${skillResult.copied.length} skill(s) in .cursor/skills/`);
162
+ }
163
+ }
157
164
  }
158
- // Upgrade Claude commands if installed, or create them if CLAUDE.md exists but .claude/commands/ doesn't
159
- // (handles upgrade from pre-0.5.4 where Claude didn't have native commands)
165
+ // Upgrade Claude commands and skills if installed
160
166
  if (claudeAdapterInstalled || claudeMdExists) {
161
167
  const result = await setupClaudeCommands(cwd, sourceCommandsDir, true); // skipPrompts = true for upgrade
162
168
  if (result.copied.length > 0) {
163
169
  const action = claudeAdapterInstalled ? 'Updated' : 'Created';
164
170
  p.log.success(`${action} ${result.copied.length} command(s) in .claude/commands/`);
165
171
  }
172
+ if (existsSync(sourceSkillsDir)) {
173
+ const skillResult = await setupSkills(cwd, sourceSkillsDir, '.claude/skills', true);
174
+ if (skillResult.copied.length > 0) {
175
+ const action = claudeAdapterInstalled ? 'Updated' : 'Created';
176
+ p.log.success(`${action} ${skillResult.copied.length} skill(s) in .claude/skills/`);
177
+ }
178
+ }
166
179
  }
167
180
  // Regenerate adapter files
168
181
  const adaptersToRegenerate = [];
@@ -67,7 +67,8 @@ export function copyFrameworkFiles(targetDir) {
67
67
  'AGENTS.md',
68
68
  'doc-templates',
69
69
  'commands',
70
- 'prompts'
70
+ 'prompts',
71
+ 'skills'
71
72
  ];
72
73
  for (const item of frameworkItems) {
73
74
  const srcItem = join(payloadPath, item);
@@ -175,7 +176,8 @@ export function copyFrameworkFilesFrom(sourcePayloadPath, targetDir) {
175
176
  'AGENTS.md',
176
177
  'doc-templates',
177
178
  'commands',
178
- 'prompts'
179
+ 'prompts',
180
+ 'skills'
179
181
  ];
180
182
  for (const item of frameworkItems) {
181
183
  const srcItem = join(sourcePayloadPath, item);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flight-rules",
3
- "version": "0.15.3",
3
+ "version": "0.15.6",
4
4
  "description": "An opinionated framework for AI-assisted software development",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/payload/AGENTS.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Flight Rules – Agent Guidelines
2
2
 
3
- flight_rules_version: 0.15.3
3
+ flight_rules_version: 0.15.6
4
4
 
5
5
  This file defines how agents (Claude Code, Cursor, etc.) should work on software projects using the Flight Rules system.
6
6
 
@@ -0,0 +1,206 @@
1
+ ---
2
+ name: skill-improve
3
+ description: >
4
+ Research-driven skill improvement. Analyzes an existing skill for weaknesses, then
5
+ searches the internet extensively for popular similar skills, prompts, and techniques
6
+ from the community (GitHub repos, awesome-lists, prompt engineering resources, official
7
+ Anthropic docs) to find ideas worth incorporating. Produces a prioritized improvement
8
+ report and implements approved changes. Use this skill whenever the user says things like
9
+ "improve this skill", "make this skill better", "enhance skill", "optimize skill",
10
+ "research better approaches for this skill", "find ways to improve this skill",
11
+ "what are other people doing for skills like this", "benchmark this skill against others",
12
+ or "level up this skill". Also trigger when the user wants to compare their skill against
13
+ community alternatives or find inspiration from popular skills in the ecosystem.
14
+ ---
15
+
16
+ # Skill Improver
17
+
18
+ Improve an existing skill by combining internal analysis with extensive internet research.
19
+ The goal is to find concrete, actionable improvements — not generic advice — by studying
20
+ what the best similar skills in the ecosystem actually do.
21
+
22
+ ## How it works
23
+
24
+ 1. **Understand the skill** — Read it deeply, understand its purpose and mechanics
25
+ 2. **Analyze internally** — Find structural and content issues
26
+ 3. **Research externally** — Search the internet for similar popular skills and techniques
27
+ 4. **Compare and synthesize** — Extract the best ideas from what you found
28
+ 5. **Report** — Present prioritized recommendations to the user
29
+ 6. **Implement** — Apply the approved improvements
30
+
31
+ ## Step 1: Understand the target skill
32
+
33
+ Ask the user which skill to improve if not already specified. Then read the skill file
34
+ thoroughly. Before doing anything else, write a brief summary of:
35
+
36
+ - What the skill does
37
+ - How it's structured (sections, flow, resources)
38
+ - What triggers it (the description field)
39
+ - What tools/techniques it uses
40
+ - Any bundled resources (scripts, references, assets)
41
+
42
+ Share this summary with the user to confirm you understand the skill correctly. Misunderstanding
43
+ the skill's purpose will lead to bad recommendations.
44
+
45
+ ## Step 2: Internal analysis
46
+
47
+ Examine the skill against these quality dimensions. Be specific — cite line numbers or
48
+ quote passages when noting issues.
49
+
50
+ ### Structure and clarity
51
+ - Is the flow logical? Would someone following it step-by-step get good results?
52
+ - Are instructions clear enough that a model can follow them without guessing?
53
+ - Is there unnecessary repetition or bloat that could be cut?
54
+ - Are there gaps where the model would need to improvise?
55
+
56
+ ### Description quality
57
+ - Does the description cover the right trigger phrases?
58
+ - Is it specific enough to avoid false triggers?
59
+ - Is it "pushy" enough to trigger when it should? (Skills tend to under-trigger)
60
+
61
+ ### Instruction effectiveness
62
+ - Are there heavy-handed MUST/NEVER/ALWAYS directives that could be replaced with
63
+ explanations of *why* something matters?
64
+ - Are examples included where they'd help?
65
+ - Is the skill explaining the reasoning behind its instructions, or just giving orders?
66
+
67
+ ### Progressive disclosure
68
+ - Is the SKILL.md under 500 lines? If longer, should content move to reference files?
69
+ - Are bundled resources referenced clearly with guidance on when to read them?
70
+
71
+ ### Robustness
72
+ - Does it handle edge cases the user might encounter?
73
+ - Are there implicit assumptions that could fail in different contexts?
74
+
75
+ Produce a concise internal analysis report organized by dimension.
76
+
77
+ ## Step 3: External research
78
+
79
+ This is the core differentiator of this skill. Search the internet extensively to find
80
+ popular, well-regarded skills and techniques that address similar problems. The goal is
81
+ to discover ideas, patterns, and approaches the current skill is missing.
82
+
83
+ ### Where to search
84
+
85
+ Run multiple searches across these categories. Use subagents for parallel research when
86
+ available — this step benefits enormously from breadth.
87
+
88
+ **Similar skills in the ecosystem:**
89
+ - Search GitHub for skills with similar names or purposes
90
+ (e.g., `claude skill [topic]`, `awesome claude skills [topic]`)
91
+ - Check curated lists: `awesome-claude-skills`, `awesome-claude-code-toolkit`
92
+ - Look for skills on the Claude Skills directory if available
93
+ - Search for Cursor rules, Windsurf rules, or other AI coding tool configurations
94
+ that address the same domain
95
+
96
+ **Prompt engineering techniques:**
97
+ - Search for prompt engineering patterns relevant to the skill's domain
98
+ - Look for academic or blog posts on techniques like chain-of-thought, few-shot
99
+ examples, self-correction, or structured output formats
100
+ - Check the Anthropic documentation for relevant best practices
101
+
102
+ **Domain-specific best practices:**
103
+ - If the skill targets a specific domain (e.g., testing, code review, documentation),
104
+ search for industry best practices in that domain
105
+ - Look for popular tools, linters, or frameworks that encode domain expertise
106
+
107
+ **Community discussions:**
108
+ - Search for discussions about similar workflows on GitHub issues, forums, or blogs
109
+ - Look for "how I use Claude for X" posts that might reveal techniques
110
+
111
+ ### What to extract from each source
112
+
113
+ For each relevant source you find, note:
114
+
115
+ - **Source**: URL and brief description
116
+ - **Key technique or pattern**: What does it do that's interesting?
117
+ - **Relevance**: How does this relate to the skill being improved?
118
+ - **Adoption signal**: Stars, installs, mentions — is this actually popular/proven?
119
+ - **Adaptability**: How easily could this be incorporated into the current skill?
120
+
121
+ ### Research depth
122
+
123
+ Aim for at least 5-8 distinct sources across the categories above. Quality matters more
124
+ than quantity — a single well-designed skill that solves the same problem is worth more
125
+ than ten tangentially related blog posts.
126
+
127
+ If the skill's domain is niche and you can't find direct comparables, broaden the search
128
+ to adjacent domains or look for transferable patterns from popular skills in other domains.
129
+
130
+ ## Step 4: Compare and synthesize
131
+
132
+ Now bring together your internal analysis and external research. For each finding from
133
+ the research, ask:
134
+
135
+ - Does the current skill already do this? If so, does it do it as well?
136
+ - Would incorporating this idea make the skill meaningfully better?
137
+ - Is this idea compatible with the skill's existing approach, or would it require
138
+ a significant restructure?
139
+ - Is this a proven pattern (used in multiple popular skills) or a one-off experiment?
140
+
141
+ Organize your findings into a synthesis that highlights the gaps between the current
142
+ skill and the best practices you found.
143
+
144
+ ## Step 5: Present the improvement report
145
+
146
+ Present a structured report to the user with three sections:
147
+
148
+ ### High-priority improvements
149
+ Changes that would significantly improve the skill's effectiveness. These are things
150
+ where popular, proven alternatives exist and the current skill is clearly weaker.
151
+
152
+ ### Medium-priority improvements
153
+ Useful enhancements that would make the skill more robust or cover more cases, but
154
+ the current approach isn't broken.
155
+
156
+ ### Low-priority / exploratory ideas
157
+ Interesting techniques spotted in the research that might be worth trying but aren't
158
+ clearly better than the current approach. Include these so the user can decide.
159
+
160
+ For each recommendation:
161
+ - **What to change**: Specific, actionable description
162
+ - **Why**: What problem it solves or what improvement it brings
163
+ - **Source**: Where you found this idea (with link if from external research)
164
+ - **Effort**: How much work it would take (small tweak vs. significant rewrite)
165
+
166
+ After presenting the report, ask the user which improvements they'd like to implement.
167
+
168
+ ## Step 6: Implement approved improvements
169
+
170
+ Apply the changes the user approved. When implementing:
171
+
172
+ - Make changes incrementally — don't rewrite the entire skill at once
173
+ - Preserve the skill's voice and style unless the user wants a different tone
174
+ - If a change requires restructuring, explain the new structure before doing it
175
+ - After implementing, show a summary of what changed
176
+
177
+ If the user wants to test the improvements, suggest using the skill-creator's evaluation
178
+ workflow to compare before and after.
179
+
180
+ ## Tips for effective research
181
+
182
+ **Cast a wide net, then narrow.** Start with broad searches, scan the results for the
183
+ most relevant hits, then dig deep into those. A search for "claude skill code review"
184
+ might surface a skill that has nothing to do with code review but uses a brilliant
185
+ self-correction pattern you can steal.
186
+
187
+ **Look at structure, not just content.** Sometimes the most valuable thing about a
188
+ popular skill isn't what it says but how it's organized — how it uses progressive
189
+ disclosure, how it sequences instructions, how it handles edge cases.
190
+
191
+ **Pay attention to what's missing.** If every popular skill in a domain does X and the
192
+ target skill doesn't, that's a strong signal. If no popular skill does Y and the target
193
+ skill does, ask whether Y is genuinely innovative or just unnecessary.
194
+
195
+ **Check the stars and installs.** A skill with 100K+ installs that does something
196
+ differently is stronger evidence than a blog post with 3 likes. Popularity isn't
197
+ everything, but it's a useful signal for proven approaches.
198
+
199
+ ## Notes
200
+
201
+ - This skill works best when you have web search capabilities. Without them, the
202
+ external research step is limited to what's already in your training data.
203
+ - For skills that are part of a larger system (like flight-rules commands), consider
204
+ how improvements might affect integration with other components.
205
+ - If the skill-creator skill is available, consider using its evaluation workflow
206
+ after implementing improvements to measure the impact quantitatively.
@@ -0,0 +1,263 @@
1
+ ---
2
+ name: web-prototype
3
+ description: >
4
+ Create multiple distinct design variations of a web page as HTML/CSS/JS prototypes.
5
+ Use this skill whenever the user wants to create web prototypes, page mockups, design
6
+ variations, HTML page concepts, landing page options, or explore different visual
7
+ directions for a page. Also trigger when the user asks to "try different designs",
8
+ "show me options for a page", "create page variations", or anything involving generating
9
+ multiple visual alternatives of a web page. Even if the user just says "prototype this
10
+ page" or "mock up a landing page", this skill applies.
11
+ ---
12
+
13
+ # Web Prototype Generator
14
+
15
+ Create multiple visually distinct variations of a web page so the user can compare
16
+ design directions side by side. Each variation is a standalone HTML file with inline
17
+ CSS and JavaScript — no frameworks, no build steps, just open in a browser.
18
+
19
+ ## How it works
20
+
21
+ 1. Understand what the user wants the page to do and look like
22
+ 2. Check or create the project config (`.web-prototype.json`)
23
+ 3. Generate N variations (default 5), each as different as possible
24
+ 4. Inject a shared navigation bar so the user can flip between variants
25
+
26
+ ## Step 1: Understand the request
27
+
28
+ Ask the user (if not already clear):
29
+ - What is this page? (landing page, dashboard, portfolio, form, etc.)
30
+ - What content should it include?
31
+ - Any specific features? (see Feature Library below)
32
+ - Any brand constraints? (colors, fonts, tone)
33
+ - How many variations? (default: 5)
34
+
35
+ Give the page a short kebab-case name for the folder (e.g., `landing-page`, `pricing`,
36
+ `signup-flow`). Confirm the name with the user if it's ambiguous.
37
+
38
+ ## Step 2: Project configuration
39
+
40
+ Look for `.web-prototype.json` in the project root. If it doesn't exist, create it:
41
+
42
+ ```json
43
+ {
44
+ "outputRoot": "prototypes",
45
+ "pages": {}
46
+ }
47
+ ```
48
+
49
+ Ask the user if `prototypes/` is the right output directory. If they want something
50
+ different, use their preference.
51
+
52
+ When generating a new page, add an entry to `pages`:
53
+
54
+ ```json
55
+ {
56
+ "outputRoot": "prototypes",
57
+ "pages": {
58
+ "landing-page": {
59
+ "variants": 5,
60
+ "created": "2026-03-07",
61
+ "description": "Main marketing landing page"
62
+ }
63
+ }
64
+ }
65
+ ```
66
+
67
+ The output structure is:
68
+ ```
69
+ {outputRoot}/
70
+ {page-name}/
71
+ variant-1.html
72
+ variant-2.html
73
+ ...
74
+ variant-N.html
75
+ ```
76
+
77
+ ## Step 3: Generate variations
78
+
79
+ For each variation, use the `frontend-design` skill to produce a distinctive,
80
+ production-grade design. The critical goal is **maximum visual diversity** — each
81
+ variant should feel like it came from a different designer with a different aesthetic
82
+ philosophy.
83
+
84
+ ### Diversity strategy
85
+
86
+ Before generating, plan N distinct design directions. Vary these dimensions across
87
+ the set so that no two variants share the same combination:
88
+
89
+ - **Layout**: single-column, split-screen, asymmetric grid, full-bleed sections,
90
+ card-based, editorial/magazine, bento grid
91
+ - **Visual tone**: minimal/stark, bold/maximalist, organic/soft, geometric/precise,
92
+ editorial/typographic, dark/moody, light/airy, retro/vintage, futuristic/glassmorphic
93
+ - **Color approach**: monochromatic, complementary, analogous, high-contrast,
94
+ muted/earthy, vibrant/saturated, dark mode, light mode
95
+ - **Typography**: large display type, classic serif, geometric sans, mixed type scales,
96
+ monospace accents, handwritten touches
97
+ - **Motion/interaction**: static, subtle hover effects, scroll-triggered animations,
98
+ parallax, micro-interactions
99
+ - **Spacing/density**: generous whitespace, dense/information-rich, mixed rhythm
100
+
101
+ Write out your plan (which direction each variant will take) before generating code.
102
+ Present it to the user for approval. Then generate each variant.
103
+
104
+ ### Per-variant requirements
105
+
106
+ Each variant must be:
107
+ - A single, self-contained HTML file with all CSS and JS inline
108
+ - Responsive (works on mobile and desktop)
109
+ - Production-grade visual quality — not a wireframe, not a generic template
110
+ - Populated with realistic placeholder content (not lorem ipsum — write real-sounding
111
+ headlines, descriptions, and data)
112
+
113
+ ### Using the frontend-design skill
114
+
115
+ For each variant, invoke the frontend-design skill with clear direction about the
116
+ specific aesthetic you're targeting for that variant. Tell it the design direction
117
+ (e.g., "Create a bold maximalist landing page with large typography and vibrant
118
+ complementary colors") so that each invocation produces a genuinely different result.
119
+
120
+ ## Step 4: Inject the variant navigation bar
121
+
122
+ Every generated HTML file must include the variant navigation bar. This is a floating
123
+ pill-shaped bar at the bottom-right of the viewport that lets the user click between
124
+ variants.
125
+
126
+ ### Navigation bar HTML and CSS
127
+
128
+ Insert this exactly at the end of `<body>`, before `</body>`. Replace `{N}` with the
129
+ total variant count and set the correct `href` values and `active` class.
130
+
131
+ ```html
132
+ <!-- Variant Navigation -->
133
+ <nav class="variant-nav" aria-label="Design variants">
134
+ <a href="variant-1.html" class="active" aria-current="page">1</a>
135
+ <a href="variant-2.html">2</a>
136
+ <a href="variant-3.html">3</a>
137
+ <!-- ... up to N -->
138
+ </nav>
139
+ <style>
140
+ .variant-nav {
141
+ position: fixed;
142
+ bottom: 24px;
143
+ right: 24px;
144
+ display: flex;
145
+ gap: 4px;
146
+ padding: 6px;
147
+ background: rgba(20, 20, 20, 0.55);
148
+ backdrop-filter: blur(24px) saturate(180%);
149
+ -webkit-backdrop-filter: blur(24px) saturate(180%);
150
+ border-radius: 20px;
151
+ border: 1px solid rgba(255, 255, 255, 0.15);
152
+ box-shadow:
153
+ 0 8px 32px rgba(0, 0, 0, 0.18),
154
+ 0 2px 8px rgba(0, 0, 0, 0.1),
155
+ inset 0 0.5px 0 rgba(255, 255, 255, 0.2);
156
+ z-index: 2147483647;
157
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
158
+ transition: opacity 0.3s ease;
159
+ }
160
+ .variant-nav:hover {
161
+ background: rgba(20, 20, 20, 0.7);
162
+ }
163
+ .variant-nav a {
164
+ display: flex;
165
+ align-items: center;
166
+ justify-content: center;
167
+ width: 36px;
168
+ height: 36px;
169
+ border-radius: 12px;
170
+ text-decoration: none;
171
+ font-size: 14px;
172
+ font-weight: 500;
173
+ letter-spacing: -0.01em;
174
+ color: rgba(255, 255, 255, 0.7);
175
+ text-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
176
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
177
+ background: transparent;
178
+ border: 1px solid transparent;
179
+ }
180
+ .variant-nav a:hover {
181
+ background: rgba(255, 255, 255, 0.12);
182
+ color: rgba(255, 255, 255, 0.95);
183
+ border-color: rgba(255, 255, 255, 0.08);
184
+ }
185
+ .variant-nav a.active {
186
+ background: rgba(255, 255, 255, 0.2);
187
+ color: #fff;
188
+ font-weight: 600;
189
+ border-color: rgba(255, 255, 255, 0.15);
190
+ box-shadow:
191
+ 0 2px 8px rgba(0, 0, 0, 0.15),
192
+ inset 0 0.5px 0 rgba(255, 255, 255, 0.25);
193
+ }
194
+ </style>
195
+ ```
196
+
197
+ This dark-tinted glass style is intentionally designed to be legible on any background —
198
+ light pages, dark pages, images, gradients, anything. Do not modify the nav bar styles
199
+ to match the page design. The nav bar should look identical across all variants.
200
+
201
+ Set `aria-current="page"` and the `active` class on whichever variant number matches
202
+ the current file (variant-1.html gets `active` on the "1" link, etc.).
203
+
204
+ ## Feature Library
205
+
206
+ When the user mentions any of these features by name, you already know what they mean.
207
+ Apply the implementation details described here without requiring further explanation
208
+ from the user.
209
+
210
+ ### Scrolling Parallax
211
+
212
+ **Trigger phrases**: "parallax", "scrolling parallax", "web parallax", "parallax scrolling",
213
+ "depth scrolling"
214
+
215
+ Multi-layer parallax scrolling where background elements move at different speeds than
216
+ foreground content during scroll, creating an illusion of depth.
217
+
218
+ **Implementation approach** (choose based on complexity needs):
219
+
220
+ **CSS-only (simpler, good for 2-3 layers):**
221
+ ```css
222
+ .parallax-container {
223
+ perspective: 1px;
224
+ height: 100vh;
225
+ overflow-x: hidden;
226
+ overflow-y: auto;
227
+ }
228
+ .parallax-layer-back {
229
+ transform: translateZ(-2px) scale(3);
230
+ }
231
+ .parallax-layer-mid {
232
+ transform: translateZ(-1px) scale(2);
233
+ }
234
+ .parallax-layer-front {
235
+ transform: translateZ(0);
236
+ }
237
+ ```
238
+
239
+ **JavaScript (smoother, more control, good for complex effects):**
240
+ - Use `requestAnimationFrame` for smooth 60fps updates
241
+ - Track scroll position with a passive scroll listener
242
+ - Apply `transform: translate3d(0, Ypx, 0)` to layers at different rates (e.g.,
243
+ background at 0.3x scroll speed, midground at 0.6x, foreground at 1x)
244
+ - Use `will-change: transform` on animated elements for GPU acceleration
245
+ - Consider `IntersectionObserver` to only animate visible sections
246
+
247
+ **Design considerations:**
248
+ - Parallax works best with distinct visual sections/bands
249
+ - Use high-quality background images or gradient layers
250
+ - Ensure content remains readable — parallax is decoration, not the content itself
251
+ - Disable or reduce parallax on mobile (`prefers-reduced-motion` media query)
252
+ - Add `@media (prefers-reduced-motion: reduce)` to disable parallax for accessibility
253
+
254
+ ---
255
+
256
+ ## Notes
257
+
258
+ - If the user asks for more variants of an existing page, read the config to find the
259
+ current count, generate additional variants, and update the nav bar in ALL files to
260
+ include the new total.
261
+ - If the user wants to iterate on a specific variant, make edits to that file directly
262
+ rather than regenerating from scratch.
263
+ - Always confirm the output path with the user before writing files.