Landing — Premium HTML Landing Page Generator skill

Generates a premium single-page HTML landing page with 3D CSS animations, GSAP scroll effects, and mouse-parallax depth.

by alirezarezvani·MIT license·★ 26,349 Stars on the repo·GitHub ↗

Use now

Files of Landing — Premium HTML Landing Page Generator

alirezarezvani/main1 file shown
SKILL.md
Show the full text347 lines

Landing — Premium HTML Landing Page Generator

Distinct from product-team/skills/landing-page-generator/. That skill outputs Next.js TSX components optimized for conversion / lead-gen. THIS skill outputs a single self-contained .html file optimized for premium visual experience with GSAP animations. Pick by use case.

Generate a polished, self-contained .html landing page from a text prompt or brief. The output is ONE HTML file: all CSS inline in <style>, all JS inline in <script>, only external dependencies being Google Fonts + GSAP via CDN. The page is visually distinctive, animated, and production-quality.

Invocation Triggers

  • "create a landing page"
  • "build a landing page"
  • "make a landing page for X"
  • "I need a web page for Y"
  • "promotional page"
  • "product page"
  • "one-pager"
  • "web presence"
  • "sales page"
  • "landing for X"

Delivery Mode

In Claude Code CLI, write the file to disk at the specified path. In Claude.ai web, create an HTML artifact with the same content.

Phase 0: Grill-Me Intake (4 forcing questions, one at a time)

Dependency-ordered. Each question carries explicit "why I'm asking". Stop condition: max 4.

Q1 (root) — Product / Service

What's the product or service? Give me the name + a 1–2 sentence elevator pitch — what does it do, and who's it for?

Why I'm asking: The headline, subtext, and feature copy all derive from this. "App for productivity" produces generic boilerplate; "Async standup tool for remote engineering teams who hate Zoom" produces a landing page that converts.

Refuse mush. If user gives just a name with no pitch, push back once: "What does it do? Who's it for?" If still no pitch after push-back, deliver with explicit "generic positioning" caveat.

Q2 (depends on Q1) — Audience Register

Who's the audience? Pick one:

  1. Technical buyers (engineers, ops, security)
  2. Business buyers (PMs, execs, ops leaders)
  3. Consumers (general public, hobbyists)
  4. Internal (employees, partners — not for public sale)

Why I'm asking: Audience dictates copy register, jargon level, social-proof choices, and CTA framing. Technical buyers want specifics; consumers want benefits; internal pages can skip persuasion.

Forcing choice.

Q3 (always) — Brand Overrides

Brand colors / fonts to override the default (dark navy + teal + Inter)? Provide as: primary HEX, accent HEX, optional bg HEX. Or say "default" if you want the polished default.

Why I'm asking: The default is intentionally beautiful, but matching your brand makes the page feel native to your existing site. Even just a primary color override goes a long way.

Accept "default" or partial overrides (e.g., just primary). If only primary provided, derive accent algorithmically (lighten / darken).

Q4 (depends on Q1) — Tone

Tone — pick one:

  1. Professional — confident, restrained, B2B-friendly
  2. Playful — warm, light, occasional humor
  3. Authoritative — expert, data-forward, trust-building
  4. Minimal — terse, design-led, low copy density

Why I'm asking: Tone affects every sentence — headlines, microcopy, button text, closing copy. Picking upfront prevents tonal whiplash across sections.

Forcing choice. Recommended default: professional if Q2 = technical/business; playful if Q2 = consumer; minimal if the product is design-led.

Stop condition: After Q4, commit and generate. No follow-up questions during generation.

Content Extraction (with Fallback Strategy)

From Q1's elevator pitch, derive:

  • Hero headline — punchy version of "what it does" (8–12 words)
  • Hero subtext — version of "who it's for + payoff" (1–2 sentences)
  • 3–6 feature bullets — distilled from pitch + audience (Q2) + tone (Q4)
  • CTA text — action-oriented, matches tone
  • Closing copy — short, emotive, matches tone

Fallback when input is sparse: invent compelling content from product-name semantics + audience register. Flag inferred content with a comment in the HTML source (<!-- inferred: ... -->). Don't stall waiting for more input.

Brand System Specification

Default Color Palette (Dark Navy + Teal)
:root {
  --navy:       #0A1628;
  --navy-mid:   #0D1F38;
  --teal:       #00D4AA;
  --teal-glow:  rgba(0, 212, 170, 0.12);
  --amber:      #F5A623;
  --off-white:  #F7F7F2;
  --text-muted: rgba(247, 247, 242, 0.68);
  --card-bg:    rgba(0, 212, 170, 0.06);
  --card-border:rgba(0, 212, 170, 0.15);
}
Override Pattern

When Q3 provides custom brand values, the skill substitutes them into the :root block:

Brand override:
- primary: #FF6B35    →  --navy / hero bg
- accent:  #2EC4B6    →  --teal / CTA / highlights
- bg:      #011627    →  --navy-mid / section bg
- text:    #FDFFFC    →  --off-white

If only primary provided, derive accent algorithmically (lighten 15% for accent; darken 8% for navy-mid; convert to rgba at 0.12 alpha for glow). Use scripts/brand_palette_validator.py for the deterministic derivation.

See references/brand_system_design.md for color theory + WCAG + algorithmic palette derivation canon.

Typography
  • Font family: Inter (via Google Fonts)
  • Weight scale: 400 (body), 500 (eyebrow), 600 (links), 700 (subtitle), 800 (H1 + H2)
  • Size scale:
    • Hero H1: 68–82px
    • Section H2: 52–62px
    • Card titles: 22px
    • Body: 17–19px
    • Eyebrow: 13px (uppercase, letter-spaced)
    • CTA button: 18px (500 weight)
Components (Must Specify CSS)
  • .btn-primary — CTA button with hover state (lift + brightness)
  • .feature-card — card with hover lift (translateY(-6px) + border-brighten)
  • .eyebrow — letter-spaced (0.2em) uppercase category label

Section 1: Hero

  • min-height: 100vh, flex-centered content
  • Optional eyebrow label above H1
  • H1 (68–82px, 800 weight)
  • Subtitle (17–19px, 1–2 sentences)
  • CTA button (.btn-primary)
  • Scroll-down indicator (animated chevron, CSS bounce)
  • Depth layers (mouse parallax):
    • .hero-shapes-back — large blurred circles, absolute-positioned, low opacity
    • .hero-shapes-mid — smaller shapes, sharper edges, higher opacity
    • Content layer (H1 + subtitle) — moves subtly in same direction as mouse

Section 2: Features

  • 3 columns default (repeat(3, 1fr) grid)
  • Responsive:
    • 2 columns at 900px breakpoint
    • 1 column at 580px breakpoint
  • Each card:
    • SVG icon (28px, stroke=var(--teal), no fill)
    • Title (22px, 700 weight)
    • Description (15–16px, --text-muted)
  • Hover state:
    • transform: translateY(-6px)
    • border-color: var(--teal) (brighten from --card-border)
    • transition: 0.3s ease

Section 3: Closing CTA

  • Full-width, background: var(--navy-mid)
  • padding: 120px 24px, text-align: center
  • Large closing headline (52–62px, 800 weight)
  • Short subtext (--text-muted, 1–2 sentences)
  • CTA button with ambient radial-gradient glow behind it:
    background: radial-gradient(circle, var(--teal-glow) 0%, transparent 70%);
    

Animation Patterns

See references/gsap_animation_patterns.md for the canon. Five patterns required:

1. Hero Entrance (GSAP timeline)
// MUST use gsap.set() FIRST to prevent FOUC
gsap.set([".eyebrow", ".hero h1", ".hero .subtitle", ".btn-primary", ".scroll-down"], {
  opacity: 0,
  y: 30
});

const tl = gsap.timeline({ defaults: { ease: "power3.out" } });
tl.to(".eyebrow", { opacity: 1, y: 0, duration: 0.6 })
  .to(".hero h1", { opacity: 1, y: 0, duration: 0.8 }, "-=0.3")
  .to(".hero .subtitle", { opacity: 1, y: 0, duration: 0.6 }, "-=0.5")
  .to(".btn-primary", { opacity: 1, y: 0, duration: 0.5 }, "-=0.3")
  .to(".scroll-down", { opacity: 1, y: 0, duration: 0.4 }, "-=0.2");
2. Mouse Parallax
const hero = document.querySelector(".hero");
hero.addEventListener("mousemove", (e) => {
  const x = (e.clientX / window.innerWidth - 0.5) * 2;
  const y = (e.clientY / window.innerHeight - 0.5) * 2;
  gsap.to(".hero-shapes-back", { x: x * 45, y: y * 22, duration: 0.8 });
  gsap.to(".hero-shapes-mid",  { x: x * 22, y: y * 11, duration: 0.8 });
  gsap.to(".hero .container",  { x: x * 8,  y: y * 5,  duration: 0.8 });
});
3. Scroll-Triggered Feature Cards
gsap.set(".feature-card", { opacity: 0, y: 55, rotateX: 18 });

ScrollTrigger.batch(".feature-card", {
  start: "top 80%",
  onEnter: batch => gsap.to(batch, {
    opacity: 1, y: 0, rotateX: 0,
    duration: 0.8,
    stagger: 0.11,
    ease: "power2.out"
  })
});
4. Floating Decorative Shapes (CSS keyframes — NOT GSAP)

CSS handles ambient continuous motion (smoother, cheaper than GSAP for indefinite animations):

@keyframes floatA {
  0%, 100% { transform: translate(0, 0) rotate(0deg); }
  50%      { transform: translate(20px, -30px) rotate(8deg); }
}
@keyframes floatB { /* different duration + rotation */ }
@keyframes floatC { /* different duration + rotation */ }

.hero-shapes-back .shape-a { animation: floatA 12s ease-in-out infinite; }
5. Scroll Indicator (CSS bounce)
@keyframes bounce {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(8px); }
}
.scroll-down { animation: bounce 2s ease-in-out infinite; }

Required CDN Dependencies

<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/ScrollTrigger.min.js"></script>

NO other external CSS or JS files. All custom CSS in <style>, all custom JS in <script> blocks within the same HTML file.

See references/single_file_html_discipline.md for the inline-only rationale.

Layout Rules

  • Container max-width: 1200px, centered
  • Section padding: 120px 24px (vertical 120, horizontal 24, scales down on mobile)
  • Responsive breakpoints:
    • 900px → features grid 3-col → 2-col
    • 580px → all grids → 1-col; H1 scales down to ~52px
  • Viewport meta: <meta name="viewport" content="width=device-width, initial-scale=1">

Output Spec

  • Path: ${OUTPUT_DIR}/<product-name-kebab>.html
  • Default ${OUTPUT_DIR}: ./landing-pages/
  • Filename: lowercase kebab-case from product name ("Quill AI" → quill-ai.html). Use scripts/kebab_slug_generator.py for deterministic slug generation + duplicate detection.
  • Self-contained: all CSS in <style>, all JS in <script>, only Google Fonts + GSAP CDN external.

Validation (Post-Generation)

Run scripts/html_validator.py --file ${OUTPUT_DIR}/<slug>.html after generation. Checks:

  • All 3 required sections present (.hero, .features, .closing-cta)
  • CDN deps present (Inter + GSAP + ScrollTrigger)
  • gsap.set() initial states precede any gsap.timeline or gsap.to (FOUC prevention)
  • Responsive breakpoints at 900px + 580px
  • No external <link rel="stylesheet"> other than Google Fonts
  • No external <script src=> other than GSAP CDN
  • <meta name="viewport"> present
  • All animated elements have initial-state declarations

Error Handling

Situation Behavior
Input is just a name with no context Invent compelling content from name semantics + audience register; flag as <!-- inferred --> in HTML source
Input file is large or PDF Read fully before generating; don't truncate
Brand colors insufficient (only 1 HEX provided) Use as primary; derive secondary/accent algorithmically (lighten/darken via brand_palette_validator.py)
Features count not specified Default to 4
Output dir doesn't exist Create it
Existing file at output path Append timestamp suffix or ask user (kebab_slug_generator.py flags duplicates)
html_validator returns FAIL Regenerate ONLY the failing sections in one targeted pass; do NOT abandon the file

Portability

  • Claude Code CLI: Native — writes HTML file directly to filesystem.
  • Claude.ai web: Native — produces HTML as an artifact instead of file.

Tooling

Script Role
scripts/brand_palette_validator.py Validates HEX format, checks WCAG AA contrast, generates derived palette from primary (algorithmic lighten/darken).
scripts/kebab_slug_generator.py Product name → kebab-case filename + duplicate detection in output dir.
scripts/html_validator.py Post-generation structural check: 3 sections, CDN deps, gsap.set() initial states, responsive breakpoints, no external files.

References

Anti-Patterns To Reject

  • Hardcoded absolute paths in output directory
  • Single brand palette without override documentation
  • Outlining before writing — write in one pass
  • External CSS or JS files (must be inline; only Google Fonts + GSAP CDN allowed)
  • Skipping gsap.set() initial states (causes FOUC)
  • More than 6 features in default grid (becomes unscannable)
  • Brand-specific content references in the skill itself

Version: 1.0.0 Source spec: megaprompts/04-landing-megaprompt.md (maintainer-local draft spec — gitignored, not present in the public repository) Build pattern: Path B (direct conversion). Distinct from product-team/skills/landing-page-generator/.

1---
2name: landing
3description: "Generates a premium single-page HTML landing page with 3D CSS animations, GSAP scroll effects, and mouse-parallax depth. Forcing intake (product + elevator pitch, audience register, brand overrides, tone) locks down positioning before any copy or markup is written, so the page reflects the actual product rather than generic boilerplate. Use whenever the user says 'landing for X', 'create a landing page', 'build a landing page', 'make a landing page for X', 'I need a web page for Y', or provides product/service details and wants a polished website. Also triggers on 'promotional page', 'product page', 'one-pager', 'web presence', 'sales page'. Outputs a single self-contained HTML file (Claude Code) or HTML artifact (Claude.ai). Supports configurable brand colors via CSS custom property overrides."
4license: MIT
5metadata:
6 source_spec: "megaprompts/04-landing-megaprompt.md"
7 build_pattern: "Path B (direct conversion)"
8 distinct_from: "product-team/skills/landing-page-generator (different output format + optimization target)"
9 version: 1.0.0
10---
11 
12# Landing — Premium HTML Landing Page Generator
13 
14> **Distinct from `product-team/skills/landing-page-generator/`.** That skill outputs Next.js TSX components optimized for conversion / lead-gen. THIS skill outputs a single self-contained `.html` file optimized for premium visual experience with GSAP animations. Pick by use case.
15 
16Generate a polished, self-contained `.html` landing page from a text prompt or brief. The output is ONE HTML file: all CSS inline in `<style>`, all JS inline in `<script>`, only external dependencies being Google Fonts + GSAP via CDN. The page is visually distinctive, animated, and production-quality.
17 
18## Invocation Triggers
19 
20- "create a landing page"
21- "build a landing page"
22- "make a landing page for X"
23- "I need a web page for Y"
24- "promotional page"
25- "product page"
26- "one-pager"
27- "web presence"
28- "sales page"
29- "landing for X"
30 
31## Delivery Mode
32 
33In **Claude Code CLI**, write the file to disk at the specified path. In **Claude.ai web**, create an HTML artifact with the same content.
34 
35## Phase 0: Grill-Me Intake (4 forcing questions, one at a time)
36 
37Dependency-ordered. Each question carries explicit "why I'm asking". Stop condition: max 4.
38 
39### Q1 (root) — Product / Service
40 
41> **What's the product or service? Give me the name + a 1–2 sentence elevator pitch — what does it do, and who's it for?**
42>
43> *Why I'm asking:* The headline, subtext, and feature copy all derive from this. "App for productivity" produces generic boilerplate; "Async standup tool for remote engineering teams who hate Zoom" produces a landing page that converts.
44 
45**Refuse mush.** If user gives just a name with no pitch, push back once: "What does it do? Who's it for?" If still no pitch after push-back, deliver with explicit "generic positioning" caveat.
46 
47### Q2 (depends on Q1) — Audience Register
48 
49> **Who's the audience? Pick one:**
50>
51> 1. **Technical buyers** (engineers, ops, security)
52> 2. **Business buyers** (PMs, execs, ops leaders)
53> 3. **Consumers** (general public, hobbyists)
54> 4. **Internal** (employees, partners — not for public sale)
55>
56> *Why I'm asking:* Audience dictates copy register, jargon level, social-proof choices, and CTA framing. Technical buyers want specifics; consumers want benefits; internal pages can skip persuasion.
57 
58Forcing choice.
59 
60### Q3 (always) — Brand Overrides
61 
62> **Brand colors / fonts to override the default (dark navy + teal + Inter)? Provide as: primary HEX, accent HEX, optional bg HEX. Or say "default" if you want the polished default.**
63>
64> *Why I'm asking:* The default is intentionally beautiful, but matching your brand makes the page feel native to your existing site. Even just a primary color override goes a long way.
65 
66Accept "default" or partial overrides (e.g., just primary). If only primary provided, derive accent algorithmically (lighten / darken).
67 
68### Q4 (depends on Q1) — Tone
69 
70> **Tone — pick one:**
71>
72> 1. **Professional** — confident, restrained, B2B-friendly
73> 2. **Playful** — warm, light, occasional humor
74> 3. **Authoritative** — expert, data-forward, trust-building
75> 4. **Minimal** — terse, design-led, low copy density
76>
77> *Why I'm asking:* Tone affects every sentence — headlines, microcopy, button text, closing copy. Picking upfront prevents tonal whiplash across sections.
78 
79Forcing choice. **Recommended default:** professional if Q2 = technical/business; playful if Q2 = consumer; minimal if the product is design-led.
80 
81**Stop condition:** After Q4, commit and generate. No follow-up questions during generation.
82 
83## Content Extraction (with Fallback Strategy)
84 
85From Q1's elevator pitch, derive:
86- **Hero headline** — punchy version of "what it does" (8–12 words)
87- **Hero subtext** — version of "who it's for + payoff" (1–2 sentences)
88- **3–6 feature bullets** — distilled from pitch + audience (Q2) + tone (Q4)
89- **CTA text** — action-oriented, matches tone
90- **Closing copy** — short, emotive, matches tone
91 
92**Fallback when input is sparse:** invent compelling content from product-name semantics + audience register. Flag inferred content with a comment in the HTML source (`<!-- inferred: ... -->`). Don't stall waiting for more input.
93 
94## Brand System Specification
95 
96### Default Color Palette (Dark Navy + Teal)
97 
98```css
99:root {
100 --navy: #0A1628;
101 --navy-mid: #0D1F38;
102 --teal: #00D4AA;
103 --teal-glow: rgba(0, 212, 170, 0.12);
104 --amber: #F5A623;
105 --off-white: #F7F7F2;
106 --text-muted: rgba(247, 247, 242, 0.68);
107 --card-bg: rgba(0, 212, 170, 0.06);
108 --card-border:rgba(0, 212, 170, 0.15);
109}
110```
111 
112### Override Pattern
113 
114When Q3 provides custom brand values, the skill substitutes them into the `:root` block:
115 
116```
117Brand override:
118- primary: #FF6B35 → --navy / hero bg
119- accent: #2EC4B6 → --teal / CTA / highlights
120- bg: #011627 → --navy-mid / section bg
121- text: #FDFFFC → --off-white
122```
123 
124If only primary provided, derive accent algorithmically (lighten 15% for accent; darken 8% for navy-mid; convert to rgba at 0.12 alpha for glow). Use `scripts/brand_palette_validator.py` for the deterministic derivation.
125 
126See [`references/brand_system_design.md`](references/brand_system_design.md) for color theory + WCAG + algorithmic palette derivation canon.
127 
128### Typography
129 
130- **Font family:** Inter (via Google Fonts)
131- **Weight scale:** 400 (body), 500 (eyebrow), 600 (links), 700 (subtitle), 800 (H1 + H2)
132- **Size scale:**
133 - Hero H1: 68–82px
134 - Section H2: 52–62px
135 - Card titles: 22px
136 - Body: 17–19px
137 - Eyebrow: 13px (uppercase, letter-spaced)
138 - CTA button: 18px (500 weight)
139 
140### Components (Must Specify CSS)
141 
142- `.btn-primary` — CTA button with hover state (lift + brightness)
143- `.feature-card` — card with hover lift (translateY(-6px) + border-brighten)
144- `.eyebrow` — letter-spaced (0.2em) uppercase category label
145 
146## Section 1: Hero
147 
148- `min-height: 100vh`, flex-centered content
149- Optional eyebrow label above H1
150- H1 (68–82px, 800 weight)
151- Subtitle (17–19px, 1–2 sentences)
152- CTA button (.btn-primary)
153- Scroll-down indicator (animated chevron, CSS bounce)
154- **Depth layers** (mouse parallax):
155 - `.hero-shapes-back` — large blurred circles, absolute-positioned, low opacity
156 - `.hero-shapes-mid` — smaller shapes, sharper edges, higher opacity
157 - Content layer (H1 + subtitle) — moves subtly in same direction as mouse
158 
159## Section 2: Features
160 
161- 3 columns default (`repeat(3, 1fr)` grid)
162- Responsive:
163 - 2 columns at 900px breakpoint
164 - 1 column at 580px breakpoint
165- Each card:
166 - SVG icon (28px, stroke=var(--teal), no fill)
167 - Title (22px, 700 weight)
168 - Description (15–16px, --text-muted)
169- Hover state:
170 - `transform: translateY(-6px)`
171 - `border-color: var(--teal)` (brighten from --card-border)
172 - `transition: 0.3s ease`
173 
174## Section 3: Closing CTA
175 
176- Full-width, `background: var(--navy-mid)`
177- `padding: 120px 24px`, text-align: center
178- Large closing headline (52–62px, 800 weight)
179- Short subtext (--text-muted, 1–2 sentences)
180- CTA button with ambient radial-gradient glow behind it:
181 ```css
182 background: radial-gradient(circle, var(--teal-glow) 0%, transparent 70%);
183 ```
184 
185## Animation Patterns
186 
187See [`references/gsap_animation_patterns.md`](references/gsap_animation_patterns.md) for the canon. Five patterns required:
188 
189### 1. Hero Entrance (GSAP timeline)
190 
191```js
192// MUST use gsap.set() FIRST to prevent FOUC
193gsap.set([".eyebrow", ".hero h1", ".hero .subtitle", ".btn-primary", ".scroll-down"], {
194 opacity: 0,
195 y: 30
196});
197 
198const tl = gsap.timeline({ defaults: { ease: "power3.out" } });
199tl.to(".eyebrow", { opacity: 1, y: 0, duration: 0.6 })
200 .to(".hero h1", { opacity: 1, y: 0, duration: 0.8 }, "-=0.3")
201 .to(".hero .subtitle", { opacity: 1, y: 0, duration: 0.6 }, "-=0.5")
202 .to(".btn-primary", { opacity: 1, y: 0, duration: 0.5 }, "-=0.3")
203 .to(".scroll-down", { opacity: 1, y: 0, duration: 0.4 }, "-=0.2");
204```
205 
206### 2. Mouse Parallax
207 
208```js
209const hero = document.querySelector(".hero");
210hero.addEventListener("mousemove", (e) => {
211 const x = (e.clientX / window.innerWidth - 0.5) * 2;
212 const y = (e.clientY / window.innerHeight - 0.5) * 2;
213 gsap.to(".hero-shapes-back", { x: x * 45, y: y * 22, duration: 0.8 });
214 gsap.to(".hero-shapes-mid", { x: x * 22, y: y * 11, duration: 0.8 });
215 gsap.to(".hero .container", { x: x * 8, y: y * 5, duration: 0.8 });
216});
217```
218 
219### 3. Scroll-Triggered Feature Cards
220 
221```js
222gsap.set(".feature-card", { opacity: 0, y: 55, rotateX: 18 });
223 
224ScrollTrigger.batch(".feature-card", {
225 start: "top 80%",
226 onEnter: batch => gsap.to(batch, {
227 opacity: 1, y: 0, rotateX: 0,
228 duration: 0.8,
229 stagger: 0.11,
230 ease: "power2.out"
231 })
232});
233```
234 
235### 4. Floating Decorative Shapes (CSS keyframes — NOT GSAP)
236 
237CSS handles ambient continuous motion (smoother, cheaper than GSAP for indefinite animations):
238 
239```css
240@keyframes floatA {
241 0%, 100% { transform: translate(0, 0) rotate(0deg); }
242 50% { transform: translate(20px, -30px) rotate(8deg); }
243}
244@keyframes floatB { /* different duration + rotation */ }
245@keyframes floatC { /* different duration + rotation */ }
246 
247.hero-shapes-back .shape-a { animation: floatA 12s ease-in-out infinite; }
248```
249 
250### 5. Scroll Indicator (CSS bounce)
251 
252```css
253@keyframes bounce {
254 0%, 100% { transform: translateY(0); }
255 50% { transform: translateY(8px); }
256}
257.scroll-down { animation: bounce 2s ease-in-out infinite; }
258```
259 
260## Required CDN Dependencies
261 
262```html
263<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
264<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
265<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/ScrollTrigger.min.js"></script>
266```
267 
268NO other external CSS or JS files. All custom CSS in `<style>`, all custom JS in `<script>` blocks within the same HTML file.
269 
270See [`references/single_file_html_discipline.md`](references/single_file_html_discipline.md) for the inline-only rationale.
271 
272## Layout Rules
273 
274- **Container max-width:** 1200px, centered
275- **Section padding:** `120px 24px` (vertical 120, horizontal 24, scales down on mobile)
276- **Responsive breakpoints:**
277 - 900px → features grid 3-col → 2-col
278 - 580px → all grids → 1-col; H1 scales down to ~52px
279- **Viewport meta:** `<meta name="viewport" content="width=device-width, initial-scale=1">`
280 
281## Output Spec
282 
283- **Path:** `${OUTPUT_DIR}/<product-name-kebab>.html`
284- **Default `${OUTPUT_DIR}`:** `./landing-pages/`
285- **Filename:** lowercase kebab-case from product name ("Quill AI" → `quill-ai.html`). Use `scripts/kebab_slug_generator.py` for deterministic slug generation + duplicate detection.
286- **Self-contained:** all CSS in `<style>`, all JS in `<script>`, only Google Fonts + GSAP CDN external.
287 
288## Validation (Post-Generation)
289 
290Run `scripts/html_validator.py --file ${OUTPUT_DIR}/<slug>.html` after generation. Checks:
291 
292- All 3 required sections present (`.hero`, `.features`, `.closing-cta`)
293- CDN deps present (Inter + GSAP + ScrollTrigger)
294- `gsap.set()` initial states precede any `gsap.timeline` or `gsap.to` (FOUC prevention)
295- Responsive breakpoints at 900px + 580px
296- No external `<link rel="stylesheet">` other than Google Fonts
297- No external `<script src=>` other than GSAP CDN
298- `<meta name="viewport">` present
299- All animated elements have initial-state declarations
300 
301## Error Handling
302 
303| Situation | Behavior |
304|---|---|
305| Input is just a name with no context | Invent compelling content from name semantics + audience register; flag as `<!-- inferred -->` in HTML source |
306| Input file is large or PDF | Read fully before generating; don't truncate |
307| Brand colors insufficient (only 1 HEX provided) | Use as primary; derive secondary/accent algorithmically (lighten/darken via brand_palette_validator.py) |
308| Features count not specified | Default to 4 |
309| Output dir doesn't exist | Create it |
310| Existing file at output path | Append timestamp suffix or ask user (kebab_slug_generator.py flags duplicates) |
311| html_validator returns FAIL | Regenerate ONLY the failing sections in one targeted pass; do NOT abandon the file |
312 
313## Portability
314 
315- **Claude Code CLI:** Native — writes HTML file directly to filesystem.
316- **Claude.ai web:** Native — produces HTML as an artifact instead of file.
317 
318## Tooling
319 
320| Script | Role |
321|---|---|
322| `scripts/brand_palette_validator.py` | Validates HEX format, checks WCAG AA contrast, generates derived palette from primary (algorithmic lighten/darken). |
323| `scripts/kebab_slug_generator.py` | Product name → kebab-case filename + duplicate detection in output dir. |
324| `scripts/html_validator.py` | Post-generation structural check: 3 sections, CDN deps, gsap.set() initial states, responsive breakpoints, no external files. |
325 
326## References
327 
328- [`references/brand_system_design.md`](references/brand_system_design.md) — color theory + WCAG + algorithmic palette derivation (7+ sources)
329- [`references/gsap_animation_patterns.md`](references/gsap_animation_patterns.md) — entrance timeline + ScrollTrigger reveals + mouse parallax + CSS floats + scroll indicator (7+ sources)
330- [`references/single_file_html_discipline.md`](references/single_file_html_discipline.md) — why inline + CDN-only externals + accessibility minimums + no-build rationale (7+ sources)
331 
332## Anti-Patterns To Reject
333 
334- Hardcoded absolute paths in output directory
335- Single brand palette without override documentation
336- Outlining before writing — write in one pass
337- External CSS or JS files (must be inline; only Google Fonts + GSAP CDN allowed)
338- Skipping `gsap.set()` initial states (causes FOUC)
339- More than 6 features in default grid (becomes unscannable)
340- Brand-specific content references in the skill itself
341 
342---
343 
344**Version:** 1.0.0
345**Source spec:** `megaprompts/04-landing-megaprompt.md` (maintainer-local draft spec — gitignored, not present in the public repository)
346**Build pattern:** Path B (direct conversion). Distinct from `product-team/skills/landing-page-generator/`.
347 

Discussion

Alternatives

Ad library teardownUse when the user wants to analyze active ads from Meta/Facebook, Google, or LinkedIn ad libraries; tear down a competitor's messaging; extract hooks, offers, CTAs, video transcripts, landing page claims, and test ideas from public ads.Creator · MITPricing Page (High‑Conversion) — Web Design SkillTell us about your plans and prices, and get back a ready-to-build pricing page: plan layout, what each tier includes, buttons, and answers to common buyer questions.Business & ops · MITCopywriting hooksWrites opening hooks and post titles for long-form articles in EN or FR — blog posts, Substack/Medium/dev.to, LinkedIn long-form, newsletters, essays. Trigger whenever the user asks for a hook, opening, lede, intro, first sentence/paragraph, opener, accroche, attaque, phrase d'accroche, or première phrase — including punching up a flat intro or draft opening — or for a post title, titre d'article, or headline. Do NOT trigger for social posts (LinkedIn feed, Twitter/X, TikTok, Bluesky), READMEs, taglines, email subjects, ad copy, landing-page headlines, press releases, SEO meta, or body rewrites. Do NOT use for end-of-article CTAs — use samber/cc-skills@copywriting-cta instead.Marketing · MITEW Skill — Sales CopyWrite sales pages, email sequences, and direct-response copy that converts through clarity and specificity rather than manipulation. Use for launches, offers, and conversion-focused email. Enforces the EW anti-AI rules, proof standards, and the writer's voice profile.Marketing · MIT