Landing pages
Turn your home page into an animated, full-width landing page with ready-made sections, your own React components, or a page you build from scratch.
Your docs site can open with a landing page instead of the first guide: a hero, feature grids, a terminal that types, a tabbed product tour, a comparison table and a call to action. Every section animates in as the reader scrolls, works in light and dark mode, and needs no React.
The home page of this site is built exactly this way. Its source is apps/docs/content/index.mdx.
Three ways to build one
| Approach | You write | Use it when |
|---|---|---|
| Sections in MDX | Markdown and section components | You want a polished page fast. Most sites stop here. |
| MDX plus your components | A React component, used next to the sections | One part needs something custom: a pricing table, a live demo. |
| A custom React page | app/(home)/page.tsx | You want full control and still the site's navbar, search and theme. |
Make the home page a landing page
Set the layout
Add layout: landing to the frontmatter of content/index.mdx. The page renders full width under the top navigation, with no sidebar, and it drops out of the sidebar.
---
title: Acme API
description: Payments for platforms.
layout: landing
---Add sections
Sections are MDX components: no import needed. Mix them with Markdown in any order.
<Hero
title="Payments for platforms"
highlight="platforms"
description="Accept payments, pay out sellers and stay compliant with one API."
actions={[
{ text: 'Get started', href: '/quickstart', icon: 'rocket' },
{ text: 'API reference', href: '/reference/payments', icon: 'book-open' },
]}
/>
<Features title="Everything in one API">
<Feature icon="zap" title="Fast" href="/performance">Under 100 ms at p95.</Feature>
<Feature icon="shield-check" title="Secure">SOC 2 Type II.</Feature>
<Feature icon="globe" title="Global">135 currencies.</Feature>
</Features>
<CallToAction title="Start building" actions={[{ text: 'Quickstart', href: '/quickstart' }]} />Point the Docs link at your first guide
/ is now the landing page, so send the navbar's guides link to the first guide:
export default defineConfig({
navigation: { guides: { text: 'Docs', url: '/quickstart' } },
// …
});Without layout: landing, the home page is an ordinary guide page. The sections still work there, and on any other page.
Animations respect your readers
Sections fade and slide in once, as they scroll into view. Readers who turn on "reduce motion" in their operating system see everything in place, with no movement. Animations use Motion, which @orbitdocs/next already includes.
Sections
Hero
The top of the page. Its text and buttons animate in on load, over a soft moving glow.
<Hero
badge="New: webhooks v2"
badgeHref="/webhooks"
title="Payments for platforms"
highlight="platforms"
description="Accept payments, pay out sellers and stay compliant."
backdrop="glow-grid"
align="center"
actions={[
{ text: 'Get started', href: '/quickstart', icon: 'rocket' },
{ text: 'Live demo', href: '/reference/payments', icon: 'play' },
]}
>
```ts title="checkout.ts"
const payment = await acme.payments.create({ amount: 500, currency: 'usd' });
```
</Hero>Anything inside <Hero> is its visual: a code block, an image, a <Terminal> or a <BrowserFrame>. With align="left" the visual sits beside the text; with align="center" it sits full width below it.
Prop
Type
An action is { text, href, icon?, variant? }. variant is primary, secondary or ghost. Icons are Lucide names in kebab case (rocket, book-open) or Simple Icons brands (SiGithub). Internal links get your site's base path.
Highlight
Puts any words in the brand gradient. Use it inside titles where highlight doesn't fit:
<Features title={<>Built for <Highlight>platform teams</Highlight></>}>…</Features>Section
A titled band for your own content. Features, Bento, Flow, Showcase, Comparison and ApiCards take the same heading props.
<Section eyebrow="Pricing" title="Pay for what you use" description="No minimums." align="center">
Any Markdown or component here.
</Section>Prop
Type
Features
A grid of cards that appear one after another. Hovering a card makes a glow follow the pointer; a card with href lifts and shows an arrow.
<Features eyebrow="Platform" title="Everything in one API" columns={3}>
<Feature icon="zap" title="Fast" href="/performance">Under 100 ms at p95.</Feature>
<Feature icon="shield-check" title="Secure">SOC 2 Type II.</Feature>
<Feature icon="SiGithub" title="Open source" href="https://github.com/acme/sdk">MIT licensed.</Feature>
</Features>Prop
Type
Bento
An asymmetric grid. Each item spans part of a six-column row and can hold a visual under its text: a code block, an image or a <Terminal>. Plan rows that add up to six: lg + sm, md + md, or three sm.
<Bento eyebrow="Everything in the box" title="Every feature, free">
<BentoItem size="lg" icon="book-open" title="API reference" description="Try every endpoint." href="/reference/payments">
```ts
await acme.payments.create({ amount: 500 });
```
</BentoItem>
<BentoItem size="sm" icon="pen-line" title="Guides" description="MDX next to your code." href="/guides" />
<BentoItem size="md" icon="package" title="SDKs" description="Six languages.">
<Terminal lines={['$ npx orbitdocs sdk', '✓ typescript']} />
</BentoItem>
<BentoItem size="md" icon="flask-conical" title="Mock server" description="Realistic responses." />
</Bento>Prop
Type
Terminal
A terminal that types its commands and prints their output when it scrolls into view. Readers can replay it and copy the commands. Lines starting with $ are commands, # comments, everything else output.
<Terminal
title="my-api"
lines={[
'$ npx orbitdocs init',
'✓ Created docs/',
'$ cd docs && npx orbitdocs dev',
'▲ Ready on http://localhost:3000',
]}
/>Prop
Type
CodeShowcase
Text on one side, code on the other. Put fenced code blocks, <Tabs> or a <Terminal> inside. reverse swaps the sides.
<CodeShowcase eyebrow="Webhooks" title="Events you can trust" description="Every event is signed." actions={[{ text: 'Webhook guide', href: '/webhooks' }]}>
```json title="payment.succeeded"
{ "type": "payment.succeeded", "data": { "id": "pay_123" } }
```
</CodeShowcase>Flow
Numbered steps joined by a line that draws itself in. Three or four steps read best. On phones the steps stack and the line runs down the side.
<Flow eyebrow="How it works" title="Three steps to your first payment" align="center">
<FlowStep icon="key" title="Get a key">Create a test key in the dashboard.</FlowStep>
<FlowStep icon="code" title="Make a request">Call `POST /v1/payments`.</FlowStep>
<FlowStep icon="rocket" title="Go live">Swap in your live key.</FlowStep>
</Flow>Leave out icon to show the step number instead.
Showcase
A product tour: tabs on one side, a large visual on the other. It plays through the tabs on its own (a progress bar shows the time left) until the reader picks one. Pair it with <BrowserFrame> screenshots.
<Showcase eyebrow="The product" title="One site for everything">
<ShowcaseItem title="API reference" icon="book-open" description="Every endpoint, with samples.">
<BrowserFrame url="docs.acme.com/reference" src="/screens/reference.png" srcDark="/screens/reference-dark.png" />
</ShowcaseItem>
<ShowcaseItem title="API client" icon="send" description="Send real requests.">
<BrowserFrame url="docs.acme.com/client" src="/screens/client.png" />
</ShowcaseItem>
</Showcase>Prop
Type
BrowserFrame
A browser window around a screenshot or any content. It tilts back flat as it scrolls into view. Give a dark-mode screenshot in srcDark and each reader sees the one that matches their theme.
<BrowserFrame url="docs.acme.com" src="/screens/home.png" srcDark="/screens/home-dark.png" alt="The Acme docs home page" />Prop
Type
Taking good screenshots
Capture at 1440 × 900 with a device pixel ratio of 2 and save as PNG or WebP in public/screens/. Take one in light and one in dark mode.
Stats
A row of big numbers. Numbers count up when they scroll into view, keeping any text around them: "12", "99.95%", "< 120 ms", "10k+".
<Stats>
<Stat value="135" label="currencies" />
<Stat value="99.99%" label="uptime last year" />
<Stat value="< 80 ms" label="p95 latency" />
</Stats>Comparison
A feature table with a ✓ or – per column. highlight tints one column, by default the first.
<Comparison
title="Acme vs. the rest"
columns={['Acme', 'Others']}
rows={[
{ feature: 'Instant payouts', values: [true, false] },
{ feature: 'Webhooks', note: 'signed, retried for 3 days', values: [true, true] },
{ feature: 'Price', values: ['0.9%', '2.9%'] },
]}
/>A value is true (✓), false (–) or a short text. On phones the table scrolls sideways.
ApiCards
One card per API in orbitdocs.config.ts, with its version, endpoint count and groups. Pass ids to show some of them.
<ApiCards eyebrow="APIs" title="Explore the APIs" ids={['payments', 'payouts']} />Logos
A row of logos, brand icons or wordmarks. marquee scrolls them in an endless loop that pauses on hover.
<Logos title="Trusted by teams at" marquee>
<Logo name="Northwind" src="/logos/northwind.svg" />
<Logo name="GitHub" icon="SiGithub" />
<Logo name="Contoso" />
</Logos><Logo> shows src if given, otherwise the icon and the name. href makes it a link.
CallToAction
The closing banner, framed by a slowly turning gradient.
<CallToAction
title="Start building today"
description="Free test keys, no credit card."
actions={[{ text: 'Get your key', href: '/quickstart', icon: 'key' }]}
/>LinkButton
A single button anywhere in MDX:
<LinkButton href="/quickstart" icon="rocket">Get started</LinkButton>
<LinkButton href="https://github.com/acme/sdk" variant="secondary" icon="SiGithub">GitHub</LinkButton>Footer
Every landing page ends with the site footer: your logo and a tagline, columns of links, social icons, and a bottom row with the copyright and small links. Fill it in orbitdocs.config.ts:
navigation: {
footer: {
description: 'Payments for platforms.', // defaults to site.description
columns: [
{ title: 'Product', links: [{ text: 'API reference', url: '/reference/payments' }] },
{ title: 'Resources', links: [{ text: 'Quickstart', url: '/quickstart' }, { text: 'Status', url: 'https://status.acme.com' }] },
],
social: [{ text: 'X', url: 'https://x.com/acme', icon: 'SiX' }], // site.github is added on its own
links: [{ text: 'Privacy', url: '/privacy' }],
copyright: '© 2026 Acme, Inc.', // default: © <year> <site.title>; false hides it
poweredBy: true, // "Built with OrbitDocs"
// "Built by <logo>", linked: credit the team behind the site
builtBy: { name: 'Acme', url: 'https://acme.com', logo: { light: '/acme.png', dark: '/acme-white.png' } },
},
},builtBy shows text (default "Built by") and the logo, or the name when there's no logo. The name becomes the logo's alt text.
With no navigation.footer, the footer still shows the logo, site.description, the GitHub icon and the copyright. A custom React page wrapped in LandingLayout gets the same footer; render <SiteFooter config={orbit} /> yourself anywhere else.
Add your own React components
Your docs app is a normal Next.js app, so a landing page can use any component you write. Create it, then add it to the components the home page passes to MDX.
Write the component
Animated components run in the browser, so start the file with 'use client'. Motion is available; add it to your docs app with npm install motion.
'use client';
import { motion } from 'motion/react';
export function Pricing() {
return (
<motion.div className="not-prose" initial={{ opacity: 0, y: 24 }} whileInView={{ opacity: 1, y: 0 }} viewport={{ once: true }}>
{/* your pricing table */}
</motion.div>
);
}Register it for the home page
import { Pricing } from '@/components/pricing';
// in Home():
<HomePage
config={orbit}
tree={guidesTree(source.getPageTree())}
page={page}
components={{ ...orbitMdxComponents(orbit, { a: createRelativeLink(source, page) }), Pricing }}
/>Use it in MDX
<Section title="Pricing" align="center">
<Pricing />
</Section>To reuse the built-in entrance animation, import Reveal, RevealGroup and RevealItem from @orbitdocs/next:
import { Reveal } from '@orbitdocs/next';
<Reveal delay={0.1}>
<YourCard />
</Reveal>The animated controller-to-reference demo at the top of this site's home page is a component like this. See components/extract-demo.tsx.
Build the page in React
app/(home)/page.tsx is your file. Replace it with any React page and wrap it in LandingLayout, so the navbar, search, theme switch and Ask AI stay the same as on every other page. The section components work in TSX too.
import { CallToAction, Features, Feature, Hero, LandingLayout } from '@orbitdocs/next';
import { orbit } from '@/lib/orbit';
export default function Home() {
return (
<LandingLayout config={orbit}>
<main className="od-landing">
<Hero title="Payments for platforms" actions={[{ text: 'Get started', href: '/quickstart' }]} />
<Features title="Why Acme">
<Feature icon="zap" title="Fast">Under 100 ms.</Feature>
</Features>
<CallToAction title="Start building" />
</main>
</LandingLayout>
);
}<ApiCards> reads your APIs from the config, so in TSX use it through the MDX components (orbitMdxComponents(orbit).ApiCards) rather than importing it directly.
Styling
Landing sections use the site theme: --color-fd-primary is the main brand colour. Override these in app/global.css:
.od-landing {
--od-accent-2: #ec4899; /* second gradient colour (default violet #8b5cf6) */
--od-landing-max: 1200px; /* content width (default 1180px) */
}Every section has a stable class (od-hero, od-bento, od-flow, od-terminal, od-cta…) for further changes.

