
Landing Page Generator
- 659 installs
- 23.5k repo stars
- Updated July 17, 2026
- alirezarezvani/claude-skills
landing-page-generator is a Claude agent skill that produces conversion-focused Next.js/React TSX landing pages with Tailwind CSS, real copy frameworks, SEO metadata, and Core Web Vitals targets for developers launching
About
landing-page-generator is a generator skill that outputs complete Next.js/React TypeScript components styled with Tailwind CSS for high-converting marketing pages. It assembles hero sections, feature grids, pricing tables, FAQ accordions, testimonial blocks, and CTA sections using proven copy frameworks PAS, AIDA, and BAB instead of placeholder lorem ipsum. The skill also emits SEO meta tags, structured data, and performance-optimized code targeting Core Web Vitals with LCP under 1 second and CLS under 0.1. Developers reach for landing-page-generator when creating a homepage, campaign page, promo page, lead-capture form page, or A/B test variant for a single-page site. It fits validate-stage work where copy and conversion matter more than full app architecture.
- 5 hero variants: centered, split, gradient, video-bg, minimal
- Copy frameworks PAS, AIDA, and BAB—not lorem ipsum
- Pricing tables (2–4 tiers), FAQ accordion with schema, testimonial blocks
- SEO meta tags and structured data; performance targets LCP < 1s, CLS < 0.1, FID < 100ms
- Full TSX + Tailwind output for Next.js/React
Landing Page Generator by the numbers
- 659 all-time installs (skills.sh)
- Ranked #515 of 2,244 Frontend Development skills by installs in the Skillselion catalog
- Security screen: LOW risk (skills.sh audit)
- Data as of Jul 31, 2026 (Skillselion catalog sync)
npx skills add https://github.com/alirezarezvani/claude-skills --skill landing-page-generatorAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 659 |
|---|---|
| repo stars | ★ 23.5k |
| Security audit | 3 / 3 scanners passed |
| Last updated | July 17, 2026 |
| Repository | alirezarezvani/claude-skills ↗ |
How do you build a high-converting Next.js landing page?
Generate a conversion-focused Next.js/React landing page with real copy, Tailwind sections, and Core Web Vitals targets—not placeholder text.
Who is it for?
Frontend developers who need a production-ready marketing landing page with real copy, Tailwind layout, and SEO metadata in one generation pass.
Skip if: Teams building multi-route SaaS dashboards, authenticated app shells, or backend APIs without a standalone marketing page requirement.
When should I use this skill?
The user asks to create a landing page, homepage, campaign page, lead-capture page, promo page, or A/B test variant with conversion-focused copy.
What you get
Complete Next.js/React TSX components with Tailwind styling, conversion copy, SEO metadata, structured data, and performance-tuned sections.
- TSX landing page components
- SEO metadata and structured data
By the numbers
- Uses three copy frameworks: PAS, AIDA, and BAB
- Targets LCP under 1s and CLS under 0.1 for Core Web Vitals
Files
Landing Page Generator
Generate high-converting landing pages from a product description. Output complete Next.js/React components with multiple section variants, proven copy frameworks, SEO optimization, and performance-first patterns. Not lorem ipsum — actual copy that converts.
Target: LCP < 1s · CLS < 0.1 · FID < 100ms Output: TSX components + Tailwind styles + SEO meta + copy variants
---
Core Capabilities
- 5 hero section variants (centered, split, gradient, video-bg, minimal)
- Feature sections (grid, alternating, cards with icons)
- Pricing tables (2–4 tiers with feature lists and toggle)
- FAQ accordion with schema markup
- Testimonials (grid, carousel, single-quote)
- CTA sections (banner, full-page, inline)
- Footer (simple, mega, minimal)
- 4 design styles with Tailwind class sets
---
Generation Workflow
Follow these steps in order for every landing page request:
1. Gather inputs — collect product name, tagline, audience, pain point, key benefit, pricing tiers, design style, and copy framework using the trigger format below. Ask only for missing fields. 2. Analyze brand voice (recommended) — if the user has existing brand content (website copy, blog posts, marketing materials), run it through marketing-skill/skills/content-production/scripts/brand_voice_analyzer.py to get a voice profile (formality, tone, perspective). Use the profile to inform design style and copy framework selection:
- formal + professional → enterprise style, AIDA framework
- casual + friendly → bold-startup style, BAB framework
- professional + authoritative → dark-saas style, PAS framework
- casual + conversational → clean-minimal style, BAB framework
3. Select design style — map the user's choice (or infer from brand voice analysis) to one of the four Tailwind class sets in the Design Style Reference. 4. Apply copy framework — write all headline and body copy using the chosen framework (PAS / AIDA / BAB) before generating components. Match the voice profile's formality and tone throughout. 5. Generate sections in order — Hero → Features → Pricing → FAQ → Testimonials → CTA → Footer. Skip sections not relevant to the product. 6. Validate against SEO checklist — run through every item in the SEO Checklist before outputting final code. Fix any gaps inline. 7. Output final components — deliver complete, copy-paste-ready TSX files with all Tailwind classes, SEO meta, and structured data included.
---
Triggering This Skill
Product: [name]
Tagline: [one sentence value prop]
Target audience: [who they are]
Key pain point: [what problem you solve]
Key benefit: [primary outcome]
Pricing tiers: [free/pro/enterprise or describe]
Design style: dark-saas | clean-minimal | bold-startup | enterprise
Copy framework: PAS | AIDA | BAB---
Design Style Reference
| Style | Background | Accent | Cards | CTA Button |
|---|---|---|---|---|
| Dark SaaS | bg-gray-950 text-white | violet-500/400 | bg-gray-900 border border-gray-800 | bg-violet-600 hover:bg-violet-500 |
| Clean Minimal | bg-white text-gray-900 | blue-600 | bg-gray-50 border border-gray-200 rounded-2xl | bg-blue-600 hover:bg-blue-700 |
| Bold Startup | bg-white text-gray-900 | orange-500 | shadow-xl rounded-3xl | bg-orange-500 hover:bg-orange-600 text-white |
| Enterprise | bg-slate-50 text-slate-900 | slate-700 | bg-white border border-slate-200 shadow-sm | bg-slate-900 hover:bg-slate-800 text-white |
Bold Startup headings: addfont-black tracking-tightto all<h1>/<h2>elements.
---
Copy Frameworks
PAS (Problem → Agitate → Solution)
- H1: Painful state they're in
- Sub: What happens if they don't fix it
- CTA: What you offer
- Example — H1: "Your team wastes 3 hours a day on manual reporting" / Sub: "Every hour spent on spreadsheets is an hour not closing deals. Your competitors are already automated." / CTA: "Automate your reports in 10 minutes →"
AIDA (Attention → Interest → Desire → Action)
- H1: Bold attention-grabbing statement → Sub: Interesting fact or benefit → Features: Desire-building proof points → CTA: Clear action
BAB (Before → After → Bridge)
- H1: "[Before state] → [After state]" → Sub: "Here's how [product] bridges the gap" → Features: How it works (the bridge)
---
Representative Component: Hero (Centered Gradient — Dark SaaS)
Use this as the structural template for all hero variants. Swap layout classes, gradient direction, and image placement for split, video-bg, and minimal variants.
export function HeroCentered() {
return (
<section className="relative flex min-h-screen flex-col items-center justify-center overflow-hidden bg-gray-950 px-4 text-center">
<div className="absolute inset-0 bg-gradient-to-b from-violet-900/20 to-transparent" />
<div className="pointer-events-none absolute -top-40 left-1/2 h-[600px] w-[600px] -translate-x-1/2 rounded-full bg-violet-600/20 blur-3xl" />
<div className="relative z-10 max-w-4xl">
<div className="mb-6 inline-flex items-center gap-2 rounded-full border border-violet-500/30 bg-violet-500/10 px-4 py-1.5 text-sm text-violet-300">
<span className="h-1.5 w-1.5 rounded-full bg-violet-400" />
Now in public beta
</div>
<h1 className="mb-6 text-5xl font-bold tracking-tight text-white md:text-7xl">
Ship faster.<br />
<span className="bg-gradient-to-r from-violet-400 to-pink-400 bg-clip-text text-transparent">
Break less.
</span>
</h1>
<p className="mx-auto mb-10 max-w-2xl text-xl text-gray-400">
The deployment platform that catches errors before your users do.
Zero config. Instant rollbacks. Real-time monitoring.
</p>
<div className="flex flex-col items-center gap-4 sm:flex-row sm:justify-center">
<Button size="lg" className="bg-violet-600 text-white hover:bg-violet-500 px-8">
Start free trial
</Button>
<Button size="lg" variant="outline" className="border-gray-700 text-gray-300">
See how it works →
</Button>
</div>
<p className="mt-4 text-sm text-gray-500">No credit card required · 14-day free trial</p>
</div>
</section>
)
}---
Other Section Patterns
Feature Section (Alternating)
Map over a features array with { title, description, image, badge }. Toggle layout direction with i % 2 === 1 ? "lg:flex-row-reverse" : "". Use <Image> with explicit width/height and rounded-2xl shadow-xl. Wrap in <section className="py-24"> with max-w-6xl container.
Pricing Table
Map over a plans array with { name, price, description, features[], cta, highlighted }. Highlighted plan gets border-2 border-violet-500 bg-violet-950/50 ring-4 ring-violet-500/20; others get border border-gray-800 bg-gray-900. Render null price as "Custom". Use <Check> icon per feature row. Layout: grid gap-8 lg:grid-cols-3.
FAQ with Schema Markup
Inject FAQPage JSON-LD via <script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }} /> inside the section. Map FAQs with { q, a } into shadcn <Accordion> with type="single" collapsible. Container: max-w-3xl.
Testimonials, CTA, Footer
- Testimonials: Grid (
grid-cols-1 md:grid-cols-3) or single-quote hero block with avatar, name, role, and quote text. - CTA Banner: Full-width section with headline, subhead, and two buttons (primary + ghost). Add trust signals (money-back guarantee, logo strip) immediately below.
- Footer: Logo + nav columns + social links + legal. Use
border-t border-gray-800separator.
---
SEO Checklist
- [ ]
<title>tag: primary keyword + brand (50–60 chars) - [ ] Meta description: benefit + CTA (150–160 chars)
- [ ] OG image: 1200×630px with product name and tagline
- [ ] H1: one per page, includes primary keyword
- [ ] Structured data: FAQPage, Product, or Organization schema
- [ ] Canonical URL set
- [ ] Image alt text on all
<Image>components - [ ] robots.txt and sitemap.xml configured
- [ ] Core Web Vitals: LCP < 1s, CLS < 0.1
- [ ] Mobile viewport meta tag present
- [ ] Internal linking to pricing and docs
Validation step: Before outputting final code, verify every checklist item above is satisfied. Fix any gaps inline — do not skip items.
---
Performance Targets
| Metric | Target | Technique |
|---|---|---|
| LCP | < 1s | Preload hero image, use priority on Next/Image |
| CLS | < 0.1 | Set explicit width/height on all images |
| FID/INP | < 100ms | Defer non-critical JS, use loading="lazy" |
| TTFB | < 200ms | Use ISR or static generation for landing pages |
| Bundle | < 100KB JS | Audit with @next/bundle-analyzer |
---
Common Pitfalls
- Hero image not preloaded — add
priorityprop to first<Image> - Missing mobile breakpoints — always design mobile-first with
sm:prefixes - CTA copy too vague — "Get started" beats "Learn more"; "Start free trial" beats "Sign up"
- Pricing page missing trust signals — add money-back guarantee and testimonials near CTA
- No above-the-fold CTA on mobile — ensure button is visible without scrolling on 375px viewport
---
Related Skills
- Brand Voice Analyzer (
marketing-skill/skills/content-production/scripts/brand_voice_analyzer.py) — Run before generation to establish voice profile and ensure copy consistency - UI Design System (
product-team/ui-design-system/) — Generate design tokens from brand color before building the page - Competitive Teardown (
product-team/competitive-teardown/) — Competitive positioning informs landing page messaging and differentiation
High-Converting Landing Page Patterns
Overview
This reference catalogs proven landing page design patterns that drive higher conversion rates. Each pattern includes placement guidance, implementation notes, and A/B testing priorities.
Hero Section Layouts
Pattern 1: Left Copy + Right Product Screenshot
- Best for: SaaS products with a strong visual UI
- Structure: Headline, subheadline, CTA on left (60%); product screenshot on right (40%)
- Why it works: F-pattern reading leads with copy, product image provides proof
- Conversion lift: Baseline pattern, strong performer across industries
Pattern 2: Centered Copy + Full-Width Background
- Best for: Brand-driven products, consumer apps
- Structure: Centered headline, subheadline, CTA over background image/gradient
- Why it works: Focuses attention on single message, high visual impact
- Note: Ensure text contrast against background for readability
Pattern 3: Video Hero
- Best for: Complex products requiring demonstration
- Structure: Short headline + embedded video (60-90 seconds) + CTA below
- Why it works: Video explains what text cannot, increases time on page
- Note: Always include thumbnail; autoplay is often counterproductive
Pattern 4: Interactive Demo
- Best for: Developer tools, data products, design tools
- Structure: Minimal copy + embedded interactive product experience
- Why it works: Hands-on experience converts better than description
- Note: Keep demo focused on one "aha moment" workflow
Social Proof Placement
Logo Bar
- Position: Immediately below hero section
- Count: 5-7 logos for credibility without clutter
- Label: "Trusted by" or "Used by teams at"
- Selection: Mix recognizable brands with relevant industry logos
Testimonial Cards
- Position: After feature explanation sections
- Format: Photo + name + title + company + specific quote
- Best quotes: Include measurable outcomes ("Saved 10 hours/week")
- Layout: 2-3 testimonials in a row, carousel for more
Case Study Callouts
- Position: Mid-page, before pricing
- Format: Company logo + headline metric + "Read the story" link
- Example: "Acme Corp reduced onboarding time by 60%"
Social Proof Numbers
- Position: Near CTA or in dedicated trust section
- Format: Large number + descriptor (e.g., "50,000+ teams", "4.8/5 rating")
- Selection: Choose 3-4 most impressive metrics
Pricing Table Designs
Good/Better/Best (3-Tier)
- Most effective for SaaS with clear feature tiers
- Highlight recommended plan with visual emphasis
- Show annual discount prominently
- Include feature comparison matrix below
Simple Two-Tier
- Free/Pro or Starter/Professional
- Best for PLG products with clear upgrade trigger
- Minimize decision fatigue
Enterprise Custom
- Replace price with "Contact Sales" for high-ACV products
- List enterprise-specific features (SSO, SLA, dedicated support)
- Include a "Talk to Sales" CTA, not just a form
Pricing Psychology
- Anchor with highest-priced plan first (or in the middle with visual highlight)
- Use monthly price with annual billing toggle
- Show savings percentage for annual plans
- Round prices ending in 9 (e.g., $49/mo, $99/mo)
Trust Signals
Security Badges
- SOC 2, ISO 27001, GDPR compliance badges
- SSL certificate indicator
- Place near forms and payment sections
Guarantees
- Money-back guarantee with specific timeframe
- Free trial with no credit card requirement
- SLA uptime commitments
Awards & Recognition
- Industry awards (best of, top rated)
- Analyst recognition (Gartner, Forrester, G2 Leader)
- Media mentions (as seen in logos)
Real-Time Activity
- "X people signed up today" (use real data only)
- Recent activity feed
- Live user count
Urgency Elements
Ethical Urgency
- Limited-time pricing (with real deadline)
- Early adopter benefits (extra features, lower price)
- Cohort-based enrollment (actual capacity limits)
Avoid
- Fake countdown timers that reset
- False scarcity ("only 3 left" when unlimited)
- Pressure tactics that erode trust
Form Optimization
Field Reduction
- Every additional field reduces conversion ~10%
- Start with email only, progressive profiling later
- Use single-column layouts for forms
Smart Defaults
- Pre-fill country based on IP
- Auto-detect company from email domain
- Default to most popular plan
Inline Validation
- Validate fields on blur, not on submit
- Show success states (green checkmark)
- Provide helpful error messages
Multi-Step Forms
- Break long forms into 2-3 steps with progress indicator
- Put easiest questions first to build commitment
- Allow saving progress for complex forms
Mobile-First Patterns
Thumb-Friendly Design
- CTAs in thumb zone (bottom 40% of screen)
- Minimum tap target: 44x44px
- Adequate spacing between interactive elements
Content Priority
- Lead with most compelling content (no scrolling to find CTA)
- Collapse secondary information into accordions
- Use sticky CTA bar on scroll
Performance
- Target <3s load time on 3G
- Lazy-load images below fold
- Minimize JavaScript execution
A/B Testing Priority Matrix
Test these elements in order of expected impact:
| Priority | Element | Expected Impact | Effort |
|---|---|---|---|
| 1 | Headline | High | Low |
| 2 | CTA text and color | High | Low |
| 3 | Hero image/video | High | Medium |
| 4 | Social proof placement | Medium | Low |
| 5 | Form fields (fewer) | Medium | Low |
| 6 | Pricing presentation | Medium | Medium |
| 7 | Page length | Medium | High |
| 8 | Testimonial selection | Low | Low |
| 9 | Color scheme | Low | Medium |
| 10 | Font choices | Low | Low |
Testing Best Practices
- Test one variable at a time for clear attribution
- Run tests for minimum 2 weeks or 1,000 visitors per variant
- Use 95% statistical significance threshold
- Document all test results for institutional knowledge
- Winner becomes new control for next test iteration
Landing Page Copywriting Frameworks
Overview
Four copy frameworks with worked SaaS examples you can adapt. Each framework includes a complete before/after example plus specific guidelines for each section.
1. AIDA Framework (Attention - Interest - Desire - Action)
The classic direct response formula, ideal for product landing pages.
Example — Project management SaaS:
Attention: "Your Team Loses 12 Hours Every Sprint to Status Meetings"
>
Interest: "Engineering teams at Series A-C startups spend 23% of their week in sync meetings — not writing code. We tracked 847 teams over 6 months. The pattern was clear: the more people in a standup, the less code shipped that day."
>
Desire: "Teams using AsyncStand ship 31% more story points per sprint. No more 15-person standups where 13 people zone out. Replace your daily sync with a 2-minute async check-in that your engineers actually complete (94% response rate vs 67% attendance for live standups)."
>
Action: "Start Your Free 14-Day Trial — No Credit Card Required"
Attention
- Lead with a specific, quantified pain point (not vague claims)
- Weak: "Save time on meetings" → Strong: "Your Team Loses 12 Hours Every Sprint to Status Meetings"
- Keep headlines under 10 words for maximum impact
Interest
- Back up the headline with specific data or a relatable scenario
- Weak: "Meetings waste time" → Strong: "We tracked 847 teams — the more people in standup, the less code shipped that day"
- Use their language: mirror words from customer reviews, support tickets, and G2 feedback
Desire
- Stack measurable outcomes, not features
- Weak: "AI-powered async updates" → Strong: "31% more story points per sprint, 94% response rate"
- Compare directly to the status quo they already endure
Action
- Single, clear CTA with action-oriented verb
- Reduce friction: "No credit card required," "Set up in 2 minutes"
- Repeat CTA after each major content block
2. PAS Framework (Problem - Agitate - Solution)
Best for pain-point-driven products where the problem is well understood.
Example — Expense management tool:
Problem: "Your finance team is still chasing receipts in Slack DMs."
>
Agitate: "Last quarter, your team spent 46 hours manually reconciling expenses across email threads, shared drives, and 'I'll submit it later' promises. That's $4,200 in payroll — spent on data entry. And when audit season hits? Good luck finding that client dinner receipt from February."
>
Solution: "Snap a photo of the receipt. ExpenseFlow auto-extracts vendor, amount, and category in 3 seconds. Your monthly close drops from 5 days to 1. 2,400 finance teams already made the switch."
Problem
- Name the exact scenario (not the abstract category)
- Weak: "Expense tracking is hard" → Strong: "Your finance team is still chasing receipts in Slack DMs"
- Mirror language from reviews and support tickets
Agitate
- Quantify the cost in dollars, hours, or missed opportunities
- Weak: "This costs you money" → Strong: "46 hours last quarter, $4,200 in payroll — on data entry"
- Acknowledge the workarounds they've tried and why those fail too
Solution
- Lead with the user action, not the technology: "Snap a photo" not "AI-powered OCR"
- Include one proof point: number of customers, time saved, or before/after metric
- Make the mechanism clear in one sentence: what happens when they use it
3. BAB Framework (Before - After - Bridge)
Ideal for aspirational products and lifestyle-oriented landing pages.
Example — Sales enablement platform:
Before: "It's 9 PM. You're rebuilding a deck for tomorrow's demo because the prospect is in healthcare, not fintech. You copy-paste from three old decks, pray the logos are right, and rehearse the new talk track in the shower."
>
After: "It's 9 AM. You type 'healthcare, 200-bed hospital, HIPAA-concerned CTO.' DeckGen builds your slides in 40 seconds — case studies, compliance badges, ROI calculator pre-loaded. You walk into the call with the best deck your prospect has ever seen."
>
Bridge: "DeckGen connects to your CRM, learns your win patterns, and generates prospect-specific decks in under a minute. 340 AEs at companies like Stripe and Notion already use it. Start free — your first 5 decks are on us."
Before
- Describe a specific, lived moment — not an abstract pain category
- Weak: "Sales decks take too long" → Strong: "It's 9 PM. You're rebuilding a deck for tomorrow's demo..."
- Use second person and present tense to make it feel immediate
After
- Same level of specificity — show the transformed version of that exact moment
- Include a measurable outcome: "40 seconds," "best deck your prospect has ever seen"
- The after state should feel effortless compared to the before
Bridge
- Name the product explicitly and explain the mechanism in one sentence
- Include one social proof data point
- End with a low-friction CTA that connects to the after state
4. 4Ps Framework (Promise - Picture - Proof - Push)
Strong for SaaS and B2B landing pages with measurable outcomes.
Promise
- Make a clear, specific, believable promise
- Tie it to a measurable outcome
- Example: "Reduce customer churn by 25% in 90 days"
Picture
- Help the reader visualize success
- Use scenarios they can relate to
- Show the product in context (screenshots, demos)
Proof
- Back the promise with evidence
- Customer testimonials with specific results
- Case studies with before/after metrics
- Third-party validation (awards, analyst reports)
Push
- Give a compelling reason to act now
- Limited-time offer, bonus, or guarantee
- Risk reversal (money-back guarantee, free trial)
Headline Formulas
Benefit-Driven
- "Get [Desired Outcome] Without [Common Objection]"
- "[Specific Result] in [Timeframe]"
- "The [Adjective] Way to [Achieve Goal]"
Problem-Driven
- "Stop [Painful Activity]. Start [Better Alternative]."
- "Tired of [Problem]? There's a Better Way."
- "[Problem]? Not Anymore."
Social Proof-Driven
- "[Number] Teams Trust [Product] to [Outcome]"
- "Why [Notable Company] Switched to [Product]"
- "Rated #1 for [Category] by [Authority]"
Question-Driven
- "What If You Could [Desirable Outcome]?"
- "Ready to [Transformation]?"
- "Still [Painful Status Quo]?"
CTA Best Practices
Language
- Use first-person: "Start My Free Trial" > "Start Your Free Trial"
- Be specific: "Get My Report" > "Submit"
- Include benefit: "Start Saving Time" > "Sign Up"
- Add urgency naturally: "Start Free Today" > "Sign Up Now!!!"
Placement
- Primary CTA above the fold
- Repeat after each major content section
- Sticky CTA on scroll (mobile especially)
- Exit-intent as last chance
Design
- High contrast color (stands out from page palette)
- Sufficient whitespace around the button
- Large enough to tap on mobile (min 44x44px)
- Micro-copy below button to reduce anxiety ("No credit card required")
Above-the-Fold Principles
The first viewport must accomplish these goals within 5 seconds: 1. Communicate what you do - Clear, jargon-free headline 2. Show who it's for - Audience identification 3. Demonstrate value - Primary benefit or outcome 4. Provide next step - Visible CTA button 5. Build credibility - One trust signal (logo bar, metric, badge)
Above-the-Fold Checklist
- [ ] Headline states primary benefit (under 10 words)
- [ ] Subheadline adds specificity or addresses objection
- [ ] Hero image/video shows product in use
- [ ] CTA button is visible without scrolling
- [ ] At least one trust signal present
- [ ] No jargon or ambiguity in messaging
Landing Page Patterns
This reference captures high-converting page patterns and copy structures.
Hero Section Patterns
Pattern 1: Problem-Solution Hero
- Headline names the painful problem.
- Subheadline states the clear outcome.
- Primary CTA starts immediately.
- Optional supporting visual demonstrates product in context.
Pattern 2: Outcome-First Hero
- Headline leads with measurable value.
- Subheadline clarifies who the page is for.
- CTA is action-oriented and specific.
Pattern 3: Authority Hero
- Headline + trust indicator (logos, testimonial snippet, proof metric).
- Useful when category skepticism is high.
Social Proof Layouts
Logo Strip + Proof Metric
- Keep to recognizable logos.
- Add one proof metric (e.g., active users, revenue saved, hours reduced).
Testimonial Grid
- 3-6 testimonials across segments.
- Include role/company where possible.
- Prefer concrete outcomes over generic praise.
Case Study Snapshot
- Mini blocks: challenge -> approach -> measurable result.
CTA Best Practices
- Use one dominant CTA per section.
- Match CTA verb to user intent ("Start trial", "Get demo", "Run audit").
- Keep CTA copy specific; avoid vague labels like "Submit".
- Reduce friction near CTA (short form, trust indicators, no surprise commitments).
Above-the-Fold Checklist
- [ ] Clear value proposition in first viewport
- [ ] Audience clarity (who this is for)
- [ ] One primary CTA visible without scrolling
- [ ] Proof element (logos, stat, quote)
- [ ] Visual hierarchy emphasizes headline + CTA
- [ ] Mobile layout keeps CTA accessible
Conversion-Optimized Templates
SaaS Demo Page
1. Hero with problem-solution framing 2. Product walkthrough section 3. Social proof strip 4. Benefits by persona 5. Objection handling FAQ 6. Final CTA
Lead Magnet Page
1. Promise + asset preview 2. Bullet outcomes 3. Short form 4. Trust/privacy note
Product Launch Page
1. Outcome-first hero 2. Why now / differentiation 3. Feature blocks 4. Testimonials / beta feedback 5. Pricing or waitlist CTA
Headline Formulas
PAS (Problem-Agitate-Solution)
- Problem: identify the pain
- Agitate: show consequences of inaction
- Solution: position the offer as relief
Example structure: "Still [problem]? Stop [negative consequence] and start [desired outcome]."
AIDA (Attention-Interest-Desire-Action)
- Attention: pattern interrupt headline
- Interest: relevant context and stakes
- Desire: proof and benefits
- Action: concrete next step
4U Formula
- Useful: clear practical value
- Urgent: reason to act now
- Unique: differentiated promise
- Ultra-specific: concrete outcome and scope
Example structure: "Get [specific result] in [timeframe] without [common pain]."
Landing Page SEO Checklist
Overview
This checklist ensures landing pages are optimized for search engine visibility while maintaining conversion focus. Apply these checks before launching any landing page.
Meta Tags
- [ ] Title tag: Under 60 characters, includes primary keyword, ends with brand name
- [ ] Meta description: 150-160 characters, includes CTA language, unique per page
- [ ] Canonical URL: Set to prevent duplicate content issues
- [ ] Robots meta: Ensure page is indexable (
index, follow) unless intentionally noindex - [ ] Open Graph tags: og:title, og:description, og:image, og:url for social sharing
- [ ] Twitter Card tags: twitter:card, twitter:title, twitter:description, twitter:image
- [ ] Viewport meta:
<meta name="viewport" content="width=device-width, initial-scale=1">
Structured Data
- [ ] Organization schema: Company name, logo, social profiles
- [ ] Product schema: Name, description, price, availability (for product pages)
- [ ] FAQ schema: For pages with FAQ sections (rich snippet opportunity)
- [ ] Breadcrumb schema: Navigation path for deep pages
- [ ] Review schema: Aggregate rating if testimonials present (use carefully per guidelines)
- [ ] Validate: Test all structured data with Google Rich Results Test
Core Web Vitals Targets
Largest Contentful Paint (LCP) - Target: < 2.5s
- [ ] Optimize hero image (WebP format, proper dimensions)
- [ ] Preload critical resources (
<link rel="preload">) - [ ] Use CDN for static assets
- [ ] Minimize render-blocking CSS and JavaScript
First Input Delay (FID) / Interaction to Next Paint (INP) - Target: < 200ms
- [ ] Defer non-critical JavaScript
- [ ] Break up long tasks (>50ms)
- [ ] Minimize third-party script impact
- [ ] Use
requestAnimationFramefor visual updates
Cumulative Layout Shift (CLS) - Target: < 0.1
- [ ] Set explicit width/height on images and videos
- [ ] Reserve space for dynamic content (ads, embeds)
- [ ] Use
font-display: swapfor web fonts - [ ] Avoid inserting content above existing content
Keyword Placement
- [ ] H1 tag: Contains primary keyword, one per page only
- [ ] H2 tags: Include secondary keywords naturally
- [ ] First paragraph: Primary keyword appears in first 100 words
- [ ] Body copy: Natural keyword density (1-2%), no stuffing
- [ ] Image alt text: Descriptive, includes keyword where relevant
- [ ] URL slug: Short, keyword-rich, hyphen-separated
- [ ] CTA text: Consider keyword inclusion where natural
Internal Linking
- [ ] Link to relevant product/feature pages
- [ ] Link to blog content that supports the page topic
- [ ] Use descriptive anchor text (not "click here")
- [ ] Ensure landing page is linked from main navigation or sitemap
- [ ] Link to pricing page if applicable
- [ ] Limit links to avoid diluting page authority (15-20 max)
Image Optimization
- [ ] Format: Use WebP with JPEG/PNG fallback
- [ ] Compression: Lossy compression for photos, lossless for graphics
- [ ] Dimensions: Serve at exact display size (no CSS resizing)
- [ ] Alt text: Descriptive, 125 characters max, natural keyword inclusion
- [ ] File names: Descriptive, hyphenated (e.g.,
product-dashboard-screenshot.webp) - [ ] Lazy loading: Apply to images below the fold (
loading="lazy") - [ ] Responsive images: Use
srcsetfor different viewport sizes
Canonical URLs
- [ ] Self-referencing canonical on every page
- [ ] Consistent protocol (https) and trailing slash usage
- [ ] Canonical points to preferred URL version (www vs non-www)
- [ ] UTM parameters excluded from canonical URL
- [ ] Pagination handled with rel="next"/"prev" or single-page canonical
Mobile Responsiveness
- [ ] Mobile-friendly test: Pass Google Mobile-Friendly Test
- [ ] Touch targets: Minimum 44x44px, 8px spacing between targets
- [ ] Font size: Minimum 16px base font, no pinch-to-zoom needed
- [ ] Content parity: All critical content accessible on mobile
- [ ] Horizontal scroll: None present at any viewport width
- [ ] Form usability: Appropriate input types (email, tel), autocomplete attributes
- [ ] Media queries: Breakpoints at 480px, 768px, 1024px, 1200px minimum
Technical SEO
- [ ] HTTPS: SSL certificate valid and active
- [ ] Page speed: < 3s load time on mobile (test with PageSpeed Insights)
- [ ] XML sitemap: Page included in sitemap.xml
- [ ] Robots.txt: Page not blocked by robots.txt
- [ ] 404 handling: Custom 404 page with navigation
- [ ] Redirect chains: No more than 1 redirect hop
- [ ] Hreflang: Set for multi-language landing pages
Content Quality Signals
- [ ] Unique content: No duplicate content from other pages
- [ ] Content depth: Sufficient content for topic coverage (500+ words for SEO pages)
- [ ] Readability: Grade level 6-8 for broad audiences
- [ ] Freshness: Last modified date reflects recent updates
- [ ] E-E-A-T signals: Author expertise, company authority, trust indicators
#!/usr/bin/env python3
"""Landing Page Scaffolder — Generate landing pages as HTML or Next.js TSX from config.
Creates production-ready landing pages with hero sections, features,
testimonials, pricing, CTAs, and responsive design.
Usage:
python landing_page_scaffolder.py config.json --format html --output page.html
python landing_page_scaffolder.py config.json --format tsx --output LandingPage.tsx
python landing_page_scaffolder.py config.json --format json
"""
import argparse
import json
import sys
from typing import Dict, List, Any, Optional
from datetime import datetime
import html as html_module
def escape(text: str) -> str:
"""HTML-escape text."""
return html_module.escape(str(text))
# ---------------------------------------------------------------------------
# Tailwind style mappings for TSX output
# ---------------------------------------------------------------------------
DESIGN_STYLES = {
"dark-saas": {
"bg": "bg-gray-950", "text": "text-white",
"accent": "violet", "card_bg": "bg-gray-900 border border-gray-800",
"btn": "bg-violet-600 hover:bg-violet-500 text-white",
"btn_secondary": "border border-gray-700 text-gray-300 hover:bg-gray-800",
"section_alt": "bg-gray-900/50", "muted": "text-gray-400",
"border": "border-gray-800",
},
"clean-minimal": {
"bg": "bg-white", "text": "text-gray-900",
"accent": "blue", "card_bg": "bg-gray-50 border border-gray-200 rounded-2xl",
"btn": "bg-blue-600 hover:bg-blue-700 text-white",
"btn_secondary": "border border-gray-300 text-gray-700 hover:bg-gray-50",
"section_alt": "bg-gray-50", "muted": "text-gray-500",
"border": "border-gray-200",
},
"bold-startup": {
"bg": "bg-white", "text": "text-gray-900",
"accent": "orange", "card_bg": "shadow-xl rounded-3xl bg-white",
"btn": "bg-orange-500 hover:bg-orange-600 text-white",
"btn_secondary": "border-2 border-orange-500 text-orange-600 hover:bg-orange-50",
"section_alt": "bg-orange-50/30", "muted": "text-gray-500",
"border": "border-gray-200",
},
"enterprise": {
"bg": "bg-slate-50", "text": "text-slate-900",
"accent": "slate", "card_bg": "bg-white border border-slate-200 shadow-sm",
"btn": "bg-slate-900 hover:bg-slate-800 text-white",
"btn_secondary": "border border-slate-300 text-slate-700 hover:bg-slate-100",
"section_alt": "bg-white", "muted": "text-slate-500",
"border": "border-slate-200",
},
}
# ---------------------------------------------------------------------------
# TSX generators
# ---------------------------------------------------------------------------
def tsx_nav(config: Dict[str, Any], style: Dict[str, str]) -> str:
brand = config.get("brand", "Brand")
nav_links = config.get("nav_links", [])
cta = config.get("nav_cta", {"text": "Get Started", "url": "#"})
links_jsx = "\n ".join(
f'<a href="{l.get("url", "#")}" className="{style["muted"]} hover:{style["text"]} font-medium transition-colors">{l.get("text", "")}</a>'
for l in nav_links
)
return f'''function Navbar() {{
return (
<nav className="sticky top-0 z-50 {style["bg"]} border-b {style["border"]} backdrop-blur-sm">
<div className="mx-auto flex max-w-7xl items-center justify-between px-6 py-4">
<a href="#" className="text-xl font-bold {style["text"]}">{brand}</a>
<div className="hidden items-center gap-8 md:flex">
{links_jsx}
<a href="{cta.get("url", "#")}" className="rounded-lg {style["btn"]} px-5 py-2.5 text-sm font-semibold transition-colors">
{cta.get("text", "Get Started")}
</a>
</div>
</div>
</nav>
);
}}'''
def tsx_hero(hero: Dict[str, Any], style: Dict[str, str]) -> str:
h1 = hero.get("headline", "Your Headline Here")
sub = hero.get("subheadline", "")
primary_cta = hero.get("primary_cta", {"text": "Get Started", "url": "#"})
secondary_cta = hero.get("secondary_cta", None)
secondary_jsx = ""
if secondary_cta:
secondary_jsx = f'''
<a href="{secondary_cta.get("url", "#")}" className="rounded-lg {style["btn_secondary"]} px-8 py-3 text-lg font-semibold transition-colors">
{secondary_cta.get("text", "Learn More")}
</a>'''
return f'''function Hero() {{
return (
<section className="flex min-h-[80vh] flex-col items-center justify-center px-6 py-24 text-center {style["bg"]}">
<div className="mx-auto max-w-4xl">
<h1 className="mb-6 text-5xl font-bold tracking-tight {style["text"]} md:text-7xl">
{h1}
</h1>
<p className="mx-auto mb-10 max-w-2xl text-xl {style["muted"]}">
{sub}
</p>
<div className="flex flex-col items-center gap-4 sm:flex-row sm:justify-center">
<a href="{primary_cta.get("url", "#")}" className="rounded-lg {style["btn"]} px-8 py-3 text-lg font-semibold transition-colors">
{primary_cta.get("text", "Get Started")}
</a>{secondary_jsx}
</div>
</div>
</section>
);
}}'''
def tsx_features(features: Dict[str, Any], style: Dict[str, str]) -> str:
title = features.get("title", "Features")
subtitle = features.get("subtitle", "")
items = features.get("items", [])
cards_jsx = "\n ".join(
f'''<div className="{style["card_bg"]} rounded-xl p-8">
<div className="mb-4 text-3xl">{f.get("icon", "")}</div>
<h3 className="mb-3 text-xl font-semibold {style["text"]}">{f.get("title", "")}</h3>
<p className="{style["muted"]}">{f.get("description", "")}</p>
</div>'''
for f in items
)
return f'''function Features() {{
return (
<section className="{style["section_alt"]} px-6 py-24">
<div className="mx-auto max-w-7xl">
<h2 className="mb-4 text-center text-4xl font-bold {style["text"]}">{title}</h2>
<p className="mx-auto mb-16 max-w-2xl text-center text-lg {style["muted"]}">{subtitle}</p>
<div className="grid gap-8 md:grid-cols-2 lg:grid-cols-3">
{cards_jsx}
</div>
</div>
</section>
);
}}'''
def tsx_testimonials(testimonials: Dict[str, Any], style: Dict[str, str]) -> str:
title = testimonials.get("title", "What Our Customers Say")
items = testimonials.get("items", [])
if not items:
return ""
cards_jsx = "\n ".join(
f'''<div className="rounded-xl border {style["border"]} p-8">
<p className="mb-6 text-lg italic {style["muted"]}">"{t.get("quote", "")}"</p>
<div>
<p className="font-semibold {style["text"]}">{t.get("name", "")}</p>
<p className="text-sm {style["muted"]}">{t.get("title", "")}, {t.get("company", "")}</p>
</div>
</div>'''
for t in items
)
return f'''function Testimonials() {{
return (
<section className="px-6 py-24 {style["bg"]}">
<div className="mx-auto max-w-7xl">
<h2 className="mb-16 text-center text-4xl font-bold {style["text"]}">{title}</h2>
<div className="grid gap-8 md:grid-cols-2 lg:grid-cols-3">
{cards_jsx}
</div>
</div>
</section>
);
}}'''
def tsx_pricing(pricing: Dict[str, Any], style: Dict[str, str]) -> str:
title = pricing.get("title", "Pricing")
plans = pricing.get("plans", [])
if not plans:
return ""
accent = style["accent"]
cards = []
for p in plans:
featured = p.get("featured", False)
border_cls = f"border-2 border-{accent}-500 ring-4 ring-{accent}-500/20" if featured else f"border {style['border']}"
badge = f'\n <div className="absolute -top-3 left-1/2 -translate-x-1/2 rounded-full bg-{accent}-600 px-4 py-1 text-xs font-semibold text-white">Most Popular</div>' if featured else ""
features_jsx = "\n ".join(
f'<li className="flex items-center gap-2 py-2"><span className="text-{accent}-500 font-bold">✓</span> {feat}</li>'
for feat in p.get("features", [])
)
cards.append(f'''<div className="relative rounded-2xl {border_cls} {style["card_bg"]} p-8 text-center">{badge}
<h3 className="mb-2 text-xl font-semibold {style["text"]}">{p.get("name", "")}</h3>
<div className="my-6 text-5xl font-extrabold {style["text"]}">${p.get("price", "0")}<span className="text-base font-normal {style["muted"]}">/mo</span></div>
<p className="{style["muted"]} mb-6">{p.get("description", "")}</p>
<ul className="mb-8 space-y-1 text-left {style["muted"]}">
{features_jsx}
</ul>
<a href="{p.get("cta_url", "#")}" className="block w-full rounded-lg {style["btn"]} py-3 text-center font-semibold transition-colors">
{p.get("cta_text", "Choose Plan")}
</a>
</div>''')
cards_jsx = "\n ".join(cards)
return f'''function Pricing() {{
return (
<section className="{style["section_alt"]} px-6 py-24">
<div className="mx-auto max-w-5xl">
<h2 className="mb-16 text-center text-4xl font-bold {style["text"]}">{title}</h2>
<div className="grid gap-8 lg:grid-cols-{min(len(plans), 3)}">
{cards_jsx}
</div>
</div>
</section>
);
}}'''
def tsx_cta(cta: Dict[str, Any], style: Dict[str, str]) -> str:
accent = style["accent"]
return f'''function CTASection() {{
return (
<section className="bg-{accent}-600 px-6 py-24 text-center text-white">
<div className="mx-auto max-w-3xl">
<h2 className="mb-4 text-4xl font-bold">{cta.get("headline", "Ready to get started?")}</h2>
<p className="mb-10 text-xl opacity-90">{cta.get("subheadline", "")}</p>
<a href="{cta.get("url", "#")}" className="rounded-lg bg-white px-8 py-3 text-lg font-semibold text-{accent}-600 transition-colors hover:bg-gray-100">
{cta.get("text", "Start Free Trial")}
</a>
</div>
</section>
);
}}'''
def tsx_footer(config: Dict[str, Any], style: Dict[str, str]) -> str:
brand = config.get("brand", "Company")
year = datetime.now().year
footer_text = config.get("footer_text", f"{year} {brand}. All rights reserved.")
return f'''function Footer() {{
return (
<footer className="border-t {style["border"]} {style["bg"]} px-6 py-10 text-center {style["muted"]}">
<p>© {footer_text}</p>
</footer>
);
}}'''
def generate_tsx(config: Dict[str, Any]) -> str:
"""Generate complete Next.js/React TSX landing page with Tailwind CSS."""
style_name = config.get("design_style", "clean-minimal")
style = DESIGN_STYLES.get(style_name, DESIGN_STYLES["clean-minimal"])
components = []
component_names = []
components.append(tsx_nav(config, style))
component_names.append("Navbar")
if config.get("hero"):
components.append(tsx_hero(config["hero"], style))
component_names.append("Hero")
if config.get("features"):
components.append(tsx_features(config["features"], style))
component_names.append("Features")
if config.get("testimonials") and config["testimonials"].get("items"):
components.append(tsx_testimonials(config["testimonials"], style))
component_names.append("Testimonials")
if config.get("pricing") and config["pricing"].get("plans"):
components.append(tsx_pricing(config["pricing"], style))
component_names.append("Pricing")
if config.get("cta"):
components.append(tsx_cta(config["cta"], style))
component_names.append("CTASection")
components.append(tsx_footer(config, style))
component_names.append("Footer")
title = config.get("title", "Landing Page")
meta_desc = config.get("meta_description", "")
page_body = "\n ".join(f"<{name} />" for name in component_names)
all_components = "\n\n".join(components)
return f'''// Generated by Landing Page Scaffolder — {datetime.now().strftime("%Y-%m-%d")}
// Stack: Next.js 14+ App Router, React, Tailwind CSS
// Design style: {style_name}
import type {{ Metadata }} from "next";
export const metadata: Metadata = {{
title: "{title}",
description: "{meta_desc}",
openGraph: {{
title: "{title}",
description: "{meta_desc}",
type: "website",
}},
}};
{all_components}
export default function LandingPage() {{
return (
<main>
{page_body}
</main>
);
}}
'''
# ---------------------------------------------------------------------------
# HTML generators (existing)
# ---------------------------------------------------------------------------
def generate_css(config: Dict[str, Any]) -> str:
"""Generate responsive CSS from config theme."""
theme = config.get("theme", {})
primary = theme.get("primary_color", "#2563eb")
secondary = theme.get("secondary_color", "#1e40af")
bg = theme.get("background", "#ffffff")
text_color = theme.get("text_color", "#1f2937")
font = theme.get("font", "Inter, system-ui, -apple-system, sans-serif")
return f"""
* {{ margin: 0; padding: 0; box-sizing: border-box; }}
body {{ font-family: {font}; color: {text_color}; background: {bg}; line-height: 1.6; }}
.container {{ max-width: 1200px; margin: 0 auto; padding: 0 24px; }}
nav {{ padding: 16px 0; border-bottom: 1px solid #e5e7eb; position: sticky; top: 0; background: {bg}; z-index: 100; }}
nav .container {{ display: flex; justify-content: space-between; align-items: center; }}
.nav-logo {{ font-size: 1.5rem; font-weight: 700; color: {primary}; text-decoration: none; }}
.nav-links {{ display: flex; gap: 24px; list-style: none; }}
.nav-links a {{ text-decoration: none; color: {text_color}; font-weight: 500; }}
.nav-cta {{ background: {primary}; color: white; padding: 8px 20px; border-radius: 6px; text-decoration: none; font-weight: 600; }}
.hero {{ padding: 80px 0; text-align: center; }}
.hero h1 {{ font-size: 3.5rem; font-weight: 800; line-height: 1.1; margin-bottom: 24px; max-width: 800px; margin-left: auto; margin-right: auto; }}
.hero p {{ font-size: 1.25rem; color: #6b7280; max-width: 600px; margin: 0 auto 32px; }}
.hero-cta {{ display: inline-flex; gap: 16px; }}
.btn-primary {{ background: {primary}; color: white; padding: 14px 32px; border-radius: 8px; text-decoration: none; font-weight: 600; font-size: 1.1rem; }}
.btn-secondary {{ background: transparent; color: {primary}; padding: 14px 32px; border-radius: 8px; text-decoration: none; font-weight: 600; font-size: 1.1rem; border: 2px solid {primary}; }}
.features {{ padding: 80px 0; background: #f9fafb; }}
.section-title {{ text-align: center; font-size: 2.5rem; font-weight: 700; margin-bottom: 16px; }}
.section-subtitle {{ text-align: center; color: #6b7280; font-size: 1.1rem; margin-bottom: 48px; max-width: 600px; margin-left: auto; margin-right: auto; }}
.features-grid {{ display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 32px; }}
.feature-card {{ background: white; padding: 32px; border-radius: 12px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }}
.feature-icon {{ font-size: 2rem; margin-bottom: 16px; }}
.feature-card h3 {{ font-size: 1.25rem; margin-bottom: 12px; }}
.feature-card p {{ color: #6b7280; }}
.testimonials {{ padding: 80px 0; }}
.testimonials-grid {{ display: grid; grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); gap: 24px; }}
.testimonial-card {{ padding: 32px; border: 1px solid #e5e7eb; border-radius: 12px; }}
.testimonial-text {{ font-size: 1.1rem; font-style: italic; margin-bottom: 20px; }}
.testimonial-author {{ display: flex; align-items: center; gap: 12px; }}
.author-info strong {{ display: block; }}
.author-info span {{ color: #6b7280; font-size: 0.9rem; }}
.pricing {{ padding: 80px 0; background: #f9fafb; }}
.pricing-grid {{ display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 24px; max-width: 900px; margin: 0 auto; }}
.pricing-card {{ background: white; padding: 32px; border-radius: 12px; border: 2px solid #e5e7eb; text-align: center; }}
.pricing-card.featured {{ border-color: {primary}; position: relative; }}
.pricing-card.featured::before {{ content: "Most Popular"; position: absolute; top: -12px; left: 50%; transform: translateX(-50%); background: {primary}; color: white; padding: 4px 16px; border-radius: 20px; font-size: 0.8rem; font-weight: 600; }}
.pricing-name {{ font-size: 1.25rem; font-weight: 600; margin-bottom: 8px; }}
.pricing-price {{ font-size: 3rem; font-weight: 800; margin: 16px 0; }}
.pricing-price span {{ font-size: 1rem; font-weight: 400; color: #6b7280; }}
.pricing-features {{ list-style: none; text-align: left; margin: 24px 0; }}
.pricing-features li {{ padding: 8px 0; border-bottom: 1px solid #f3f4f6; }}
.pricing-features li::before {{ content: "\\2713 "; color: {primary}; font-weight: 700; }}
.cta-section {{ padding: 80px 0; text-align: center; background: {primary}; color: white; }}
.cta-section h2 {{ font-size: 2.5rem; margin-bottom: 16px; }}
.cta-section p {{ font-size: 1.1rem; opacity: 0.9; margin-bottom: 32px; }}
.btn-white {{ background: white; color: {primary}; padding: 14px 32px; border-radius: 8px; text-decoration: none; font-weight: 600; font-size: 1.1rem; }}
footer {{ padding: 40px 0; border-top: 1px solid #e5e7eb; color: #6b7280; text-align: center; }}
@media (max-width: 768px) {{
.hero h1 {{ font-size: 2.25rem; }}
.hero-cta {{ flex-direction: column; align-items: center; }}
.nav-links {{ display: none; }}
.features-grid {{ grid-template-columns: 1fr; }}
.pricing-grid {{ grid-template-columns: 1fr; }}
}}
"""
def render_nav(config: Dict[str, Any]) -> str:
brand = escape(config.get("brand", "Brand"))
nav_links = config.get("nav_links", [])
cta = config.get("nav_cta", {"text": "Get Started", "url": "#"})
links = "\n".join(
f'<li><a href="{escape(l.get("url", "#"))}">{escape(l.get("text", ""))}</a></li>'
for l in nav_links
)
return f"""
<nav><div class="container">
<a href="#" class="nav-logo">{brand}</a>
<ul class="nav-links">{links}</ul>
<a href="{escape(cta.get('url', '#'))}" class="nav-cta">{escape(cta.get('text', 'Get Started'))}</a>
</div></nav>"""
def render_hero(hero: Dict[str, Any]) -> str:
h1 = escape(hero.get("headline", "Your Headline Here"))
sub = escape(hero.get("subheadline", ""))
primary_cta = hero.get("primary_cta", {"text": "Get Started", "url": "#"})
secondary_cta = hero.get("secondary_cta", None)
cta_html = f'<a href="{escape(primary_cta.get("url", "#"))}" class="btn-primary">{escape(primary_cta.get("text", "Get Started"))}</a>'
if secondary_cta:
cta_html += f'\n<a href="{escape(secondary_cta.get("url", "#"))}" class="btn-secondary">{escape(secondary_cta.get("text", "Learn More"))}</a>'
return f"""
<section class="hero"><div class="container">
<h1>{h1}</h1>
<p>{sub}</p>
<div class="hero-cta">{cta_html}</div>
</div></section>"""
def render_features(features: Dict[str, Any]) -> str:
title = escape(features.get("title", "Features"))
subtitle = escape(features.get("subtitle", ""))
items = features.get("items", [])
cards = "\n".join(f"""
<div class="feature-card">
<div class="feature-icon">{escape(f.get('icon', ''))}</div>
<h3>{escape(f.get('title', ''))}</h3>
<p>{escape(f.get('description', ''))}</p>
</div>""" for f in items)
return f"""
<section class="features"><div class="container">
<h2 class="section-title">{title}</h2>
<p class="section-subtitle">{subtitle}</p>
<div class="features-grid">{cards}</div>
</div></section>"""
def render_testimonials(testimonials: Dict[str, Any]) -> str:
title = escape(testimonials.get("title", "What Our Customers Say"))
items = testimonials.get("items", [])
if not items:
return ""
cards = "\n".join(f"""
<div class="testimonial-card">
<p class="testimonial-text">"{escape(t.get('quote', ''))}"</p>
<div class="testimonial-author">
<div class="author-info">
<strong>{escape(t.get('name', ''))}</strong>
<span>{escape(t.get('title', ''))}, {escape(t.get('company', ''))}</span>
</div>
</div>
</div>""" for t in items)
return f"""
<section class="testimonials"><div class="container">
<h2 class="section-title">{title}</h2>
<div class="testimonials-grid">{cards}</div>
</div></section>"""
def render_pricing(pricing: Dict[str, Any]) -> str:
title = escape(pricing.get("title", "Pricing"))
plans = pricing.get("plans", [])
if not plans:
return ""
cards = "\n".join(f"""
<div class="pricing-card {'featured' if p.get('featured') else ''}">
<div class="pricing-name">{escape(p.get('name', ''))}</div>
<div class="pricing-price">${escape(str(p.get('price', '0')))}<span>/mo</span></div>
<p>{escape(p.get('description', ''))}</p>
<ul class="pricing-features">
{"".join(f'<li>{escape(f)}</li>' for f in p.get('features', []))}
</ul>
<a href="{escape(p.get('cta_url', '#'))}" class="btn-primary">{escape(p.get('cta_text', 'Choose Plan'))}</a>
</div>""" for p in plans)
return f"""
<section class="pricing"><div class="container">
<h2 class="section-title">{title}</h2>
<div class="pricing-grid">{cards}</div>
</div></section>"""
def render_cta(cta: Dict[str, Any]) -> str:
return f"""
<section class="cta-section"><div class="container">
<h2>{escape(cta.get('headline', 'Ready to get started?'))}</h2>
<p>{escape(cta.get('subheadline', ''))}</p>
<a href="{escape(cta.get('url', '#'))}" class="btn-white">{escape(cta.get('text', 'Start Free Trial'))}</a>
</div></section>"""
def generate_html(config: Dict[str, Any]) -> str:
"""Generate complete HTML landing page."""
title = escape(config.get("title", "Landing Page"))
css = generate_css(config)
sections = []
sections.append(render_nav(config))
if config.get("hero"):
sections.append(render_hero(config["hero"]))
if config.get("features"):
sections.append(render_features(config["features"]))
if config.get("testimonials"):
sections.append(render_testimonials(config["testimonials"]))
if config.get("pricing"):
sections.append(render_pricing(config["pricing"]))
if config.get("cta"):
sections.append(render_cta(config["cta"]))
sections.append(f"""
<footer><div class="container">
<p>{escape(config.get('footer_text', f'{datetime.now().year} {config.get("brand", "Company")}. All rights reserved.'))}</p>
</div></footer>""")
return f"""<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{title}</title>
<meta name="description" content="{escape(config.get('meta_description', ''))}">
<style>{css}</style>
</head>
<body>
{"".join(sections)}
</body>
</html>"""
def main():
parser = argparse.ArgumentParser(
description="Generate landing pages as HTML or Next.js TSX with Tailwind CSS"
)
parser.add_argument("input", help="Path to page config JSON")
parser.add_argument(
"--format", choices=["html", "tsx", "json"], default="tsx",
help="Output format: tsx (Next.js + Tailwind), html (standalone), json (metadata)"
)
parser.add_argument("--output", type=str, default=None, help="Output file path")
args = parser.parse_args()
with open(args.input) as f:
config = json.load(f)
if args.format == "json":
output = json.dumps({
"generated_at": datetime.now().isoformat(),
"config": config,
"formats_available": ["html", "tsx"],
"sections": [k for k in ["nav", "hero", "features", "testimonials", "pricing", "cta", "footer"]
if config.get(k) or k in ("nav", "footer")]
}, indent=2)
elif args.format == "tsx":
output = generate_tsx(config)
else:
output = generate_html(config)
if args.output:
with open(args.output, "w") as f:
f.write(output)
print(f"Landing page written to {args.output}")
else:
print(output)
if __name__ == "__main__":
main()
Related skills
How it compares
Pick landing-page-generator over generic frontend skills when the deliverable is a conversion-focused marketing page with copy frameworks and SEO metadata, not an app feature screen.
FAQ
What frameworks does landing-page-generator use?
landing-page-generator produces Next.js/React TypeScript TSX components styled with Tailwind CSS. Output includes hero, feature grids, pricing tables, FAQ accordions, testimonial blocks, CTA sections, SEO meta tags, and structured data for campaign or homepage use.
What performance targets does landing-page-generator enforce?
landing-page-generator optimizes generated code for Core Web Vitals, targeting LCP under 1 second and CLS under 0.1. Sections are structured for conversion using PAS, AIDA, and BAB copy frameworks rather than placeholder content.
Is Landing Page Generator safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.