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

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.