Customize Marketing Pages in the Next.js Supabase Turbo Starter Kit
Build and customize landing pages, pricing pages, FAQ, and other marketing content using Next.js App Router and Tailwind CSS.
Marketing pages in Makerkit live at apps/web/app/(marketing)/ and include landing pages, pricing, FAQ, blog, documentation, and contact forms. These pages use Next.js App Router with React Server Components for fast initial loads and SEO optimization.
Marketing Pages Development
Customize and extend your marketing pages
Marketing Pages Structure
The marketing pages follow Next.js App Router conventions with a route group:
apps/web/app/(marketing)/├── layout.tsx # Shared layout with header/footer├── page.tsx # Home page (/)├── (legal)/ # Legal pages group│ ├── cookie-policy/│ ├── privacy-policy/│ └── terms-of-service/├── blog/ # Blog listing and posts├── changelog/ # Product changelog├── contact/ # Contact form├── docs/ # Documentation├── faq/ # FAQ page├── pricing/ # Pricing page└── _components/ # Shared marketing components ├── header.tsx ├── footer.tsx └── site-navigation.tsxRoute Groups Explained
The (marketing) folder is a route group that shares a layout without affecting the URL structure. Pages inside render at the root level:
| File Path | URL |
|---|---|
app/(marketing)/page.tsx | / |
app/(marketing)/pricing/page.tsx | /pricing |
app/(marketing)/blog/page.tsx | /blog |
Customizing Existing Pages
Home Page
The home page at apps/web/app/(marketing)/page.tsx typically includes:
apps/web/app/(marketing)/page.tsx
import { Hero } from './_components/hero';import { Features } from './_components/features';import { Testimonials } from './_components/testimonials';import { Pricing } from './_components/pricing-section';import { CallToAction } from './_components/call-to-action';export default function HomePage() { return ( <> <Hero /> <Features /> <Testimonials /> <Pricing /> <CallToAction /> </> );}Each section is a separate component in _components/ for easy customization.
Pricing Page
The pricing page displays your billing plans. It reads configuration from apps/web/config/billing.config.ts:
apps/web/app/(marketing)/pricing/page.tsx
import { PricingTable } from '@kit/billing-gateway/marketing';import billingConfig from '~/config/billing.config';export default function PricingPage() { return ( <div className="container py-16"> <h1 className="text-4xl font-bold text-center mb-4"> Simple, Transparent Pricing </h1> <p className="text-muted-foreground text-center mb-12"> Choose the plan that fits your needs </p> <PricingTable config={billingConfig} /> </div> );}See Billing Configuration for customizing plans and pricing.
FAQ Page
The FAQ page uses an accordion component with content from a configuration file or CMS:
apps/web/app/(marketing)/faq/page.tsx
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger,} from '@kit/ui/accordion';const faqs = [ { question: 'How do I get started?', answer: 'Sign up for a free account and follow our getting started guide.', }, { question: 'Can I cancel anytime?', answer: 'Yes, you can cancel your subscription at any time with no penalties.', }, // ... more FAQs];export default function FAQPage() { return ( <div className="container max-w-3xl py-16"> <h1 className="text-4xl font-bold text-center mb-12"> Frequently Asked Questions </h1> <Accordion type="single" collapsible> {faqs.map((faq, index) => ( <AccordionItem key={index} value={`item-${index}`}> <AccordionTrigger>{faq.question}</AccordionTrigger> <AccordionContent>{faq.answer}</AccordionContent> </AccordionItem> ))} </Accordion> </div> );}Contact Page
The contact page includes a form that sends emails via your configured mailer:
apps/web/app/(marketing)/contact/page.tsx
import { ContactForm } from './_components/contact-form';export default function ContactPage() { return ( <div className="container max-w-xl py-16"> <h1 className="text-4xl font-bold text-center mb-4"> Contact Us </h1> <p className="text-muted-foreground text-center mb-8"> Have a question? We'd love to hear from you. </p> <ContactForm /> </div> );}Contact Form Configuration
Configure the recipient email address in your environment:
.env.local
CONTACT_EMAIL=support@yourdomain.comThe form submission uses your email configuration. Ensure your mailer is configured before the contact form will work.
Creating New Marketing Pages
Basic Page Structure
Create a new page with proper metadata:
apps/web/app/(marketing)/about/page.tsx
import type { Metadata } from 'next';export const metadata: Metadata = { title: 'About Us | Your SaaS Name', description: 'Learn about our mission, team, and the story behind our product.',};export default function AboutPage() { return ( <div className="container py-16"> <h1 className="text-4xl font-bold mb-8">About Us</h1> <div className="prose prose-gray max-w-none"> <p>Your company story goes here...</p> </div> </div> );}MDX Pages for Content-Heavy Pages
For content-heavy pages, use MDX:
# Create an MDX pagemkdir -p apps/web/app/\(marketing\)/abouttouch apps/web/app/\(marketing\)/about/page.mdxapps/web/app/(marketing)/about/page.mdx
---title: "About Us"description: "Learn about our mission and team"---# About UsWe started this company because...## Our MissionTo help developers ship faster...## The TeamMeet the people behind the product...Dynamic Pages with Data
For pages that need dynamic data, combine Server Components with data fetching:
apps/web/app/(marketing)/customers/page.tsx
import { createCmsClient } from '@kit/cms';export default async function CustomersPage() { const cms = await createCmsClient(); const caseStudies = await cms.getContentItems({ collection: 'case-studies', limit: 10, }); return ( <div className="container py-16"> <h1 className="text-4xl font-bold mb-12">Customer Stories</h1> <div className="grid md:grid-cols-2 gap-8"> {caseStudies.map((study) => ( <CaseStudyCard key={study.slug} {...study} /> ))} </div> </div> );}Navigation and Footer
Header Navigation
Configure navigation links in the header component:
apps/web/app/(marketing)/_components/site-navigation.tsx
const navigationItems = [ { label: 'Features', href: '/#features' }, { label: 'Pricing', href: '/pricing' }, { label: 'Blog', href: '/blog' }, { label: 'Docs', href: '/docs' }, { label: 'Contact', href: '/contact' },];Footer Links
The footer typically includes multiple link sections:
apps/web/app/(marketing)/_components/footer.tsx
const footerSections = [ { title: 'Product', links: [ { label: 'Features', href: '/#features' }, { label: 'Pricing', href: '/pricing' }, { label: 'Changelog', href: '/changelog' }, ], }, { title: 'Resources', links: [ { label: 'Documentation', href: '/docs' }, { label: 'Blog', href: '/blog' }, { label: 'FAQ', href: '/faq' }, ], }, { title: 'Legal', links: [ { label: 'Privacy Policy', href: '/privacy-policy' }, { label: 'Terms of Service', href: '/terms-of-service' }, { label: 'Cookie Policy', href: '/cookie-policy' }, ], },];Customizing the Layout
All marketing pages inherit from apps/web/app/(marketing)/layout.tsx. This layout includes:
- Header with navigation
- Footer with links
- Common metadata
- Analytics scripts
Edit this file to change the shared structure across all marketing pages.
SEO for Marketing Pages
Metadata API
Use Next.js Metadata API for SEO:
apps/web/app/(marketing)/pricing/page.tsx
import type { Metadata } from 'next';export const metadata: Metadata = { title: 'Pricing | Your SaaS Name', description: 'Choose from flexible pricing plans. Start free, upgrade when ready.', openGraph: { title: 'Pricing | Your SaaS Name', description: 'Choose from flexible pricing plans.', images: ['/images/og/pricing.png'], },};Structured Data
Add JSON-LD structured data for rich search results:
import { JsonLd } from '@kit/ui/json-ld';export default function PricingPage() { return ( <> <JsonLd data={{ '@context': 'https://schema.org', '@type': 'Product', name: 'Your SaaS Name', offers: { '@type': 'AggregateOffer', lowPrice: '0', highPrice: '99', priceCurrency: 'USD', }, }} /> {/* Page content */} </> );}Sitemap
Add new marketing pages to your sitemap at apps/web/app/sitemap.xml/route.ts:
function getPaths() { return [ '/', '/pricing', '/faq', '/blog', '/docs', '/contact', '/about', // Add new pages here ];}Related Resources
- SEO Configuration for detailed SEO setup
- Legal Pages for privacy policy and terms
- External Marketing Website for using Framer or Webflow
- CMS Setup for blog configuration
- Email Configuration for contact form setup