CoreMVP
Customization

Landing Page

Customize the marketing landing page.

Overview

The landing page is in src/app/(marketing)/page.tsx.

Default sections:

  • Hero
  • Features
  • Pricing
  • FAQ
  • CTA

Hero Section

src/components/landing/hero-section.tsx
export function HeroSection() {
  return (
    <section className="py-24 text-center">
      <h1 className="text-5xl font-bold">
        Your Product Headline
      </h1>
      <p className="mt-4 text-xl text-muted-foreground">
        A brief description of what you offer.
      </p>
      <div className="mt-8 flex justify-center gap-4">
        <Button size="lg" asChild>
          <Link href="/signup">Get Started</Link>
        </Button>
        <Button size="lg" variant="outline" asChild>
          <Link href="/docs">Documentation</Link>
        </Button>
      </div>
    </section>
  );
}

Features Section

const features = [
  {
    title: 'Feature One',
    description: 'Description of feature one.',
    icon: <Zap className="h-6 w-6" />,
  },
  {
    title: 'Feature Two',
    description: 'Description of feature two.',
    icon: <Shield className="h-6 w-6" />,
  },
  // ...
];

export function FeaturesSection() {
  return (
    <section className="py-16">
      <h2 className="text-3xl font-bold text-center">Features</h2>
      <div className="mt-12 grid md:grid-cols-3 gap-8">
        {features.map((feature) => (
          <FeatureCard key={feature.title} {...feature} />
        ))}
      </div>
    </section>
  );
}

Pricing Section

The pricing section pulls from Stripe products:

export default async function PricingPage() {
  const products = await stripe.products.list({
    active: true,
    expand: ['data.default_price'],
  });

  return <PricingCards products={products.data} />;
}

Customizing Pricing Cards

Edit src/components/pricing/pricing-card.tsx:

function PricingCard({ product, price, popular }) {
  return (
    <Card className={popular ? 'border-primary' : ''}>
      <CardHeader>
        <CardTitle>{product.name}</CardTitle>
        <div className="text-3xl font-bold">
          ${price.unit_amount / 100}
        </div>
      </CardHeader>
      <CardContent>
        <ul className="space-y-2">
          {product.features.map((feature) => (
            <li key={feature} className="flex items-center gap-2">
              <Check className="h-4 w-4 text-green-500" />
              {feature}
            </li>
          ))}
        </ul>
        <Button className="w-full mt-6">Get Started</Button>
      </CardContent>
    </Card>
  );
}

FAQ Section

const faqs = [
  {
    question: 'What payment methods do you accept?',
    answer: 'We accept all major credit cards via Stripe.',
  },
  {
    question: 'Can I cancel my subscription?',
    answer: 'Yes, you can cancel anytime from your dashboard.',
  },
];

export function FAQSection() {
  return (
    <section className="py-16">
      <h2 className="text-3xl font-bold text-center">FAQ</h2>
      <Accordion type="single" collapsible className="mt-8 max-w-2xl mx-auto">
        {faqs.map((faq, i) => (
          <AccordionItem key={i} value={`item-${i}`}>
            <AccordionTrigger>{faq.question}</AccordionTrigger>
            <AccordionContent>{faq.answer}</AccordionContent>
          </AccordionItem>
        ))}
      </Accordion>
    </section>
  );
}

CTA Section

export function CTASection() {
  return (
    <section className="py-24 bg-primary text-primary-foreground text-center">
      <h2 className="text-3xl font-bold">Ready to get started?</h2>
      <p className="mt-4">Start your free trial today.</p>
      <Button size="lg" variant="secondary" className="mt-8" asChild>
        <Link href="/signup">Sign Up Free</Link>
      </Button>
    </section>
  );
}

Layout

Combine sections in the landing page:

src/app/(marketing)/page.tsx
export default function LandingPage() {
  return (
    <main>
      <HeroSection />
      <FeaturesSection />
      <PricingSection />
      <FAQSection />
      <CTASection />
    </main>
  );
}

Was this page helpful?

On this page