Landing Page Components
Starterbase includes 18 landing page components plus 25+ UI components. All support dark mode, i18n, and are fully responsive.
Quick Start
Import components from @/components/landing:
import {
Navbar,
Hero,
Features,
Pricing,
FAQ,
CTA,
Footer,
} from '@/components/landing';
Components
| Component | Description | Variants |
|---|---|---|
| Hero | Main headline with CTAs | Hero, HeroSimple |
| Features | Feature grid with icons | Features, FeaturesAlt |
| Pricing | Pricing plans with toggle | - |
| Testimonials | Customer testimonials grid | - |
| CTA | Call-to-action section | - |
| FAQ | Accordion FAQ | - |
| Navbar | Fixed navigation | - |
| Footer | Multi-column footer | - |
| Stats | Key metrics display | - |
| HowItWorks | Step-by-step process | - |
| Problem | Pain points section | - |
| Solution | Solution highlight | - |
| LogoCloud | Partner/client logos | - |
| Newsletter | Email signup form | - |
| PromoBanner | Dismissible banner | - |
Common Topics
- Scroll Animations - Add reveal animations
- Dark Mode - Theme support
- i18n Integration - Multi-language support
- Accessibility - WCAG compliance
- Troubleshooting - Common issues
Page Structure
The landing page uses a client/server component split for optimal SEO and hydration:
src/app/page.tsx # Server component with metadata + JSON-LD
src/components/landing/
└── LandingPageClient.tsx # Client component with lazy loading
Server Component (page.tsx)
Handles SEO metadata and structured data:
import { LandingPageClient } from '@/components/landing';
import { JsonLd, getFAQSchema } from '@/lib/seo/structured-data';
export const metadata: Metadata = {
title: { absolute: `${siteConfig.name} - ${siteConfig.tagline}` },
description: siteConfig.description,
};
export default function LandingPage() {
return (
<>
<JsonLd data={getFAQSchema(faqs)} />
<LandingPageClient />
</>
);
}
Client Component (LandingPageClient.tsx)
Handles interactivity and lazy loading:
'use client';
import { lazy, Suspense, useState } from 'react';
import dynamic from 'next/dynamic';
import { Navbar, Hero, PromoBanner } from '@/components/landing';
// Lazy load below-the-fold components
const Features = lazy(() => import('@/components/landing/Features'));
const Stats = lazy(() => import('@/components/landing/Stats'));
const HowItWorks = lazy(() => import('@/components/landing/HowItWorks'));
const Testimonials = lazy(() => import('@/components/landing/Testimonials'));
const CTA = lazy(() => import('@/components/landing/CTA'));
const Footer = lazy(() => import('@/components/landing/Footer'));
// Components with Radix UI need dynamic import to avoid hydration mismatches
const Pricing = dynamic(() => import('@/components/landing/Pricing'), { ssr: false });
const FAQ = dynamic(() => import('@/components/landing/FAQ'), { ssr: false });
const Newsletter = dynamic(() => import('@/components/landing/Newsletter'), { ssr: false });
export default function LandingPageClient() {
const [showBanner, setShowBanner] = useState(false);
return (
<div className="min-h-screen bg-white dark:bg-zinc-950">
{showBanner && <PromoBanner onDismiss={() => setShowBanner(false)} />}
<Navbar hasBanner={showBanner} />
<Hero />
<Suspense fallback={<div className="min-h-screen" />}>
<Features />
<Stats />
<HowItWorks />
<Testimonials />
<Pricing />
<FAQ />
<CTA />
<Newsletter />
<Footer />
</Suspense>
</div>
);
}
Lazy Loading
Components are loaded using two strategies:
| Strategy | Use Case | Components |
|---|---|---|
lazy() |
Standard components | Features, Stats, HowItWorks, Testimonials, CTA, Footer |
dynamic({ ssr: false }) |
Radix UI components | Pricing, FAQ, Newsletter |
💡
Hydration
Components using Radix UI or Headless UI primitives need { ssr: false } to avoid hydration ID mismatches.
Using Variants
Some components have alternative versions:
// Default Hero with logo and background pattern
import { Hero } from '@/components/landing';
// Minimal Hero without logo
import { HeroSimple } from '@/components/landing';
// Default Features with cards
import { Features } from '@/components/landing';
// Alternative Features layout
import { FeaturesAlt } from '@/components/landing';
Customization
All components read translations from src/locales/en.json under the landing key:
{
"landing": {
"hero": {
"title": "Build {brand} faster",
"subtitle": "Your subtitle here"
},
"features": { ... },
"pricing": { ... }
}
}
To customize content, edit the translation file rather than modifying components directly.