Landing page: bento
The home page of this site. A left-aligned hero with a command to copy, a bento grid of live components, color scales, type roles and a terminal, three install steps, questions and a closing call to action. Its own header and footer are optional.
Add this example to a project that has prfct installed. The command writes the files below and installs the components they use.
$ pnpm dlx shadcn@latest add https://www.prfct.dev/r/landing-bento.json"use client"
import * as React from "react"
import Link from "next/link"
import { ArrowRightIcon, CheckIcon, CopyIcon } from "lucide-react"
import { PlanCard, TeamCard } from "./landing-showcase"
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion"
import { Button, buttonVariants } from "@/components/ui/button"
import { Kbd } from "@/components/ui/kbd"
import { cn } from "@/lib/utils"
const install = "pnpm dlx shadcn@latest add https://prfct.dev/r/prfct.json"
// Links that start with "/" are prfct.dev's own pages: point them at yours.
const navigation = [
{ label: "Features", href: "#features" },
{ label: "Install", href: "#install" },
{ label: "Questions", href: "#questions" },
]
/** Steps of each scale, light to dark, as the theme names them. */
const hues = ["gray", "blue", "green", "amber", "red"]
const shades = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
const roles = [
{ name: "Display", className: "text-display-sm" },
{ name: "Heading", className: "text-heading-lg" },
{ name: "Body", className: "text-body-md" },
{ name: "Label", className: "text-label-sm" },
{ name: "Code", className: "font-mono text-sm" },
]
const brands = [
"bg-foreground",
"bg-blue-9",
"bg-green-9",
"bg-amber-9",
"bg-orange-9",
"bg-red-9",
"bg-pink-9",
]
const examples = [
{ name: "Dashboard", href: "/examples/dashboard" },
{ name: "Mail", href: "/examples/mail" },
{ name: "Checkout", href: "/examples/checkout" },
{ name: "Booking", href: "/examples/booking" },
{ name: "Team", href: "/examples/team" },
]
const steps = [
{
title: "Start a project",
text: "Create a Next.js app with shadcn. In an app you already have, leave out --template next.",
command:
"pnpm dlx shadcn@latest init --template next --base base --preset nova",
},
{
title: "Add the theme",
text: "Tokens, base styles and font faces arrive as files in your project. The guide shows the stylesheet import and the two font files to download.",
command: install,
},
{
title: "Add what you need",
text: "A single component or a whole example app. Each one brings what it depends on.",
command: "pnpm dlx shadcn@latest add https://prfct.dev/r/dashboard.json",
},
]
const questions = [
{
question: "Is prfct free?",
answer:
"Yes. It is open source under the MIT license, for personal and commercial work.",
},
{
question: "How is it different from shadcn?",
answer:
"prfct is built on shadcn's components and keeps their API. It adds generated tokens with tested contrast, a quieter look, documentation for every component and example apps.",
},
{
question: "Do I need Next.js?",
answer:
"prfct is built and tested for Next.js. The components are React and Tailwind CSS, so other React frameworks may work, but nobody has tested them.",
},
{
question: "Can I use my own brand color?",
answer:
"Yes. The theme builder regenerates every scale from one color and keeps text readable in both modes.",
},
{
question: "How do I update a component?",
answer:
"Run the add command again. The CLI asks before it replaces a file, so you can look at the change first.",
},
]
const footer = [
{
title: "Product",
links: [
{ label: "Components", href: "/docs/components" },
{ label: "Foundations", href: "/docs/foundations" },
{ label: "Themes", href: "/themes" },
{ label: "Examples", href: "/examples" },
],
},
{
title: "Resources",
links: [
{ label: "Documentation", href: "/docs" },
{ label: "Installation", href: "/docs/installation" },
{ label: "Changelog", href: "/docs/resources/changelog" },
],
},
]
/** One width and one gutter for every section. */
const container = "mx-auto w-full max-w-6xl px-4 @md:px-6"
/** Cells share hairlines: the grid's background shows through 1px gaps. */
const hairlines = "grid gap-px overflow-hidden rounded-2xl border bg-border"
const quietLink =
"rounded-md text-sm text-muted-foreground focus-ring transition-colors duration-fast hover:text-foreground"
function Logo() {
return (
<Link href="/" className="flex items-center gap-2 rounded-md focus-ring">
<svg viewBox="0 0 24 24" fill="currentColor" className="size-6">
<path d="M3 21V3a18 18 0 0 1 18 18z" />
</svg>
<span className="font-semibold tracking-tight">prfct</span>
</Link>
)
}
/** A command people copy rather than retype. */
function Command({ children }: { children: string }) {
const [copied, setCopied] = React.useState(false)
// The check mark confirms the copy for a moment, then turns back.
React.useEffect(() => {
if (!copied) return
const timer = setTimeout(() => setCopied(false), 2000)
return () => clearTimeout(timer)
}, [copied])
async function copy() {
try {
await navigator.clipboard.writeText(children)
setCopied(true)
} catch {
// No clipboard access (an insecure page, a denied permission): nothing
// was copied, so nothing is confirmed.
}
}
return (
<div className="flex max-w-full items-center gap-1 rounded-xl border bg-surface py-1 pr-1 pl-4">
<code className="truncate font-mono text-sm">
<span className="text-muted-foreground select-none">$ </span>
{children}
</code>
<Button
variant="ghost"
size="icon-sm"
aria-label={copied ? "Copied" : "Copy command"}
onClick={copy}
>
{copied ? <CheckIcon /> : <CopyIcon />}
</Button>
</div>
)
}
/** One feature: what it is in a sentence, and the thing itself below. */
function Cell({
title,
text,
className,
children,
}: {
title: string
text: string
className?: string
children: React.ReactNode
}) {
return (
<div
className={cn(
"flex flex-col gap-8 bg-background p-6 @2xl:p-8",
className
)}
>
<div className="flex flex-col gap-1.5">
<h3 className="text-heading-sm">{title}</h3>
<p className="max-w-md text-sm leading-6 text-muted-foreground">
{text}
</p>
</div>
<div className="mt-auto">{children}</div>
</div>
)
}
function Header() {
return (
<header className="border-b">
<div className={cn(container, "flex h-14 items-center gap-8")}>
<Logo />
<nav aria-label="Sections" className="flex gap-6 @max-2xl:hidden">
{navigation.map((item) => (
<a key={item.href} href={item.href} className={quietLink}>
{item.label}
</a>
))}
</nav>
<Link
href="/docs/installation"
className={buttonVariants({ size: "sm", className: "ml-auto" })}
>
Get started
</Link>
</div>
</header>
)
}
function Hero() {
return (
<section className={cn(container, "pt-14 pb-14 @2xl:pt-24 @2xl:pb-20")}>
<Link
href="/examples"
className={cn(quietLink, "group inline-flex items-center gap-2")}
>
New: example apps you can install
<ArrowRightIcon
className="size-3.5 transition-transform duration-fast group-hover:translate-x-0.5"
aria-hidden="true"
/>
</Link>
<h1 className="mt-5 text-display-sm @2xl:text-display-lg @5xl:text-display-xl">
A design system for Next.js.
<span className="block text-muted-foreground">
Built on shadcn, yours to change.
</span>
</h1>
<div className="mt-10 grid gap-8 @5xl:grid-cols-[minmax(0,1fr)_auto] @5xl:items-end">
<p className="max-w-xl text-body-lg text-pretty text-muted-foreground">
Tokens with tested contrast, accessible components and complete
example apps. You install them with the shadcn CLI, and the code is
yours.
</p>
<div className="flex min-w-0 flex-col gap-3 @5xl:items-end">
<div className="flex flex-wrap gap-3">
<Link
href="/docs/installation"
className={buttonVariants({ size: "lg" })}
>
Get started
<ArrowRightIcon data-icon="inline-end" />
</Link>
<Link
href="/docs/components"
className={buttonVariants({ variant: "outline", size: "lg" })}
>
Browse components
</Link>
</div>
<Command>{install}</Command>
</div>
</div>
</section>
)
}
function Features() {
return (
<section
id="features"
aria-labelledby="features-title"
className={cn(container, "pb-20 @2xl:pb-28")}
>
<h2 id="features-title" className="sr-only">
Features
</h2>
<div className={cn(hairlines, "@2xl:grid-cols-2 @5xl:grid-cols-6")}>
<Cell
className="@2xl:col-span-2 @5xl:col-span-4"
title="Components that agree with each other"
text="One radius, one spacing scale and one set of states, across every component."
>
{/* A picture of the system, not a form to fill in: nothing in it takes focus. */}
<div
inert
className="grid items-start gap-4 rounded-xl bg-surface p-4 @2xl:grid-cols-2"
>
<TeamCard />
<div className="@max-2xl:hidden">
<PlanCard />
</div>
</div>
</Cell>
<Cell
className="@5xl:col-span-2"
title="Contrast you don't have to check"
text="Every scale is generated, and its text steps are tested against WCAG AA on the fills they sit on, in light and dark."
>
<div className="flex flex-col gap-1.5" aria-hidden="true">
{hues.map((hue) => (
<div key={hue} className="flex gap-1.5">
{shades.map((shade) => (
<span
key={shade}
className="h-8 flex-1 rounded-sm"
style={{ backgroundColor: `var(--${hue}-${shade})` }}
/>
))}
</div>
))}
</div>
</Cell>
<Cell
className="@5xl:col-span-2"
title="Type with roles"
text="Each role sets size, line height, weight and tracking together."
>
<ul className="flex flex-col gap-2">
{roles.map((role) => (
<li key={role.name} className={cn("truncate", role.className)}>
{role.name}
</li>
))}
</ul>
</Cell>
<Cell
className="@5xl:col-span-2"
title="Usable without a mouse"
text="Keyboard support, focus management and ARIA come with every component."
>
<div className="flex flex-col items-start gap-5" aria-hidden="true">
<div className="flex flex-wrap gap-1.5">
<Kbd>Tab</Kbd>
<Kbd>Shift</Kbd>
<Kbd>Enter</Kbd>
<Kbd>Esc</Kbd>
<Kbd>←</Kbd>
<Kbd>→</Kbd>
</div>
{/* A button as it looks with keyboard focus. */}
<span
className={buttonVariants({
variant: "outline",
className: "outline-2 outline-offset-2 outline-ring",
})}
>
Focused
</span>
</div>
</Cell>
<Cell
className="@5xl:col-span-2"
title="One theme, any brand"
text="Pick a color in the theme builder. Every component follows it."
>
<div className="flex flex-col items-start gap-5">
<div className="flex gap-2" aria-hidden="true">
{brands.map((brand) => (
<span
key={brand}
className={cn("size-6 rounded-full", brand)}
/>
))}
</div>
<Link
href="/themes"
className={buttonVariants({ variant: "outline" })}
>
Open the theme builder
</Link>
</div>
</Cell>
<Cell
className="@5xl:col-span-3"
title="Code you own"
text="The shadcn CLI copies components into your project. Read them, change them, delete what you don't need."
>
<pre className="overflow-x-auto rounded-xl border bg-surface p-4 font-mono text-sm leading-6">
<span className="text-muted-foreground">$ </span>
shadcn add button{"\n"}
<span className="text-muted-foreground">
✔ components/ui/button.tsx{"\n"}✔ components/ui/spinner.tsx
{"\n"}✔ components/ui/locale.tsx{"\n"}✔ lib/utils.ts
</span>
</pre>
</Cell>
<Cell
className="@5xl:col-span-3"
title="Whole screens, not only parts"
text="Example apps you install with one command and adapt."
>
<ul className="border-t">
{examples.map((example) => (
<li key={example.href} className="border-b">
<Link
href={example.href}
className="group flex items-center justify-between rounded-md py-2.5 text-sm font-medium focus-ring"
>
{example.name}
<ArrowRightIcon
className="size-4 text-muted-foreground transition-transform duration-fast group-hover:translate-x-0.5 group-hover:text-foreground"
aria-hidden="true"
/>
</Link>
</li>
))}
</ul>
</Cell>
</div>
</section>
)
}
function Install() {
return (
<section id="install" className="border-t bg-surface">
<div className={cn(container, "py-20 @2xl:py-28")}>
<h2 className="max-w-2xl text-heading-xl text-balance @2xl:text-display-sm">
From an empty folder to a first screen
</h2>
<ol className={cn(hairlines, "mt-10")}>
{steps.map((step, index) => (
<li
key={step.title}
className="grid items-center gap-x-10 gap-y-4 bg-background p-6 @2xl:p-8 @5xl:grid-cols-[2rem_minmax(0,1fr)_auto]"
>
<span className="font-mono text-sm text-muted-foreground">
0{index + 1}
</span>
<div className="flex flex-col gap-1">
<h3 className="text-heading-sm">{step.title}</h3>
<p className="text-sm leading-6 text-muted-foreground">
{step.text}
</p>
</div>
<Command>{step.command}</Command>
</li>
))}
</ol>
</div>
</section>
)
}
function Questions() {
return (
<section id="questions" className="border-t">
<div
className={cn(
container,
"grid gap-10 py-20 @2xl:py-28 @5xl:grid-cols-[2fr_3fr]"
)}
>
<h2 className="text-heading-xl text-balance @2xl:text-display-sm">
Questions people ask before they install
</h2>
<Accordion defaultValue={[questions[0].question]}>
{questions.map((item) => (
<AccordionItem key={item.question} value={item.question}>
<AccordionTrigger>{item.question}</AccordionTrigger>
<AccordionContent>{item.answer}</AccordionContent>
</AccordionItem>
))}
</Accordion>
</div>
</section>
)
}
/** Dark in both themes, so the page ends on its one loud moment. */
function Closing() {
return (
<section className="dark border-t bg-background text-foreground">
<div
className={cn(
container,
"grid gap-10 py-20 @2xl:py-28 @5xl:grid-cols-[minmax(0,1fr)_auto] @5xl:items-end"
)}
>
<h2 className="max-w-3xl text-display-sm text-balance @2xl:text-display-lg">
Install the theme.{" "}
<span className="text-muted-foreground">
Build your first screen today.
</span>
</h2>
<div className="flex min-w-0 flex-col gap-3 @5xl:items-end">
<Link
href="/docs/installation"
className={buttonVariants({ size: "lg" })}
>
Read the installation guide
<ArrowRightIcon data-icon="inline-end" />
</Link>
<Command>{install}</Command>
</div>
</div>
</section>
)
}
function Footer() {
return (
<footer className="border-t">
<div
className={cn(
container,
"grid gap-10 py-12 @2xl:grid-cols-[2fr_1fr_1fr]"
)}
>
<div className="flex flex-col items-start gap-3">
<Logo />
<p className="max-w-xs text-sm text-muted-foreground">
A design system for Next.js, built on shadcn. Released under the MIT
license.
</p>
</div>
{footer.map((group) => (
<nav
key={group.title}
aria-label={group.title}
className="flex flex-col gap-3"
>
<h2 className="text-sm font-medium">{group.title}</h2>
<ul className="flex flex-col gap-2">
{group.links.map((link) => (
<li key={link.href}>
<Link href={link.href} className={quietLink}>
{link.label}
</Link>
</li>
))}
</ul>
</nav>
))}
</div>
</footer>
)
}
/**
* A landing page built around a bento grid: every feature is shown with the
* thing itself. `chrome` is its own header and footer: leave them out where
* the page sits inside a site that has both, as it does on prfct.dev.
*/
export default function LandingBentoExample({
chrome = true,
}: {
chrome?: boolean
}) {
return (
<div className="@container bg-background text-foreground">
{chrome && <Header />}
<Hero />
<Features />
<Install />
<Questions />
<Closing />
{chrome && <Footer />}
</div>
)
}import {
CircleCheckIcon,
GitBranchIcon,
MinusIcon,
PlusIcon,
} from "lucide-react"
import aurora from "./aurora.svg"
import ember from "./ember.svg"
import tide from "./tide.svg"
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card"
import { Checkbox } from "@/components/ui/checkbox"
import {
Field,
FieldContent,
FieldDescription,
FieldGroup,
FieldLabel,
FieldSeparator,
FieldTitle,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"
import {
InputOTP,
InputOTPGroup,
InputOTPSeparator,
InputOTPSlot,
} from "@/components/ui/input-otp"
import { Progress } from "@/components/ui/progress"
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
import { Slider } from "@/components/ui/slider"
import { Switch } from "@/components/ui/switch"
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
const people = [
{ name: "Maya Chen", role: "Owner", image: aurora.src, owner: true },
{ name: "Jonah Okafor", role: "Admin", image: ember.src },
{ name: "Lena Park", role: "Member", image: tide.src },
]
const plans = [
{ value: "hobby", title: "Hobby", description: "One project", price: "$0" },
{
value: "pro",
title: "Pro",
description: "Unlimited projects",
price: "$20",
},
]
const alerts = [
{ id: "deploys", title: "Deployments", on: true },
{ id: "comments", title: "Comments", on: true },
{ id: "digest", title: "Weekly digest", on: false },
]
function AccountCard() {
return (
<Card size="sm">
<CardHeader>
<CardTitle>Create an account</CardTitle>
<CardDescription>Start with your work email.</CardDescription>
</CardHeader>
<CardContent>
<FieldGroup>
<Field>
<FieldLabel htmlFor="showcase-name">Name</FieldLabel>
<Input id="showcase-name" defaultValue="Ada Lovelace" />
</Field>
<Field>
<FieldLabel htmlFor="showcase-email">Email</FieldLabel>
<Input id="showcase-email" placeholder="ada@example.com" />
</Field>
<Field orientation="horizontal">
<Checkbox id="showcase-updates" defaultChecked />
<FieldLabel htmlFor="showcase-updates" className="font-normal">
Send me product updates
</FieldLabel>
</Field>
<Button>Create account</Button>
<FieldSeparator>or</FieldSeparator>
<Button variant="outline">
<GitBranchIcon data-icon="inline-start" />
Continue with Git
</Button>
</FieldGroup>
</CardContent>
</Card>
)
}
export function TeamCard() {
return (
<Card size="sm">
<CardHeader>
<CardTitle>Team</CardTitle>
<CardDescription>Three people can open this project.</CardDescription>
</CardHeader>
<CardContent className="flex flex-col gap-3">
{people.map((person) => (
<div key={person.name} className="flex items-center gap-3">
<Avatar>
<AvatarImage src={person.image} alt="" />
<AvatarFallback>{person.name[0]}</AvatarFallback>
</Avatar>
<span className="flex-1 truncate text-sm font-medium">
{person.name}
</span>
<Badge variant={person.owner ? "default" : "outline"}>
{person.role}
</Badge>
</div>
))}
</CardContent>
</Card>
)
}
export function PlanCard() {
return (
<Card size="sm">
<CardHeader>
<CardTitle>Plan</CardTitle>
<CardDescription>Change it whenever you like.</CardDescription>
</CardHeader>
<CardContent>
<RadioGroup defaultValue="pro" aria-label="Plan">
{plans.map((plan) => (
<FieldLabel key={plan.value} htmlFor={`showcase-${plan.value}`}>
<Field orientation="horizontal">
<RadioGroupItem
value={plan.value}
id={`showcase-${plan.value}`}
/>
<FieldContent>
<FieldTitle>{plan.title}</FieldTitle>
<FieldDescription>{plan.description}</FieldDescription>
</FieldContent>
<span className="text-sm font-semibold tabular-nums">
{plan.price}
</span>
</Field>
</FieldLabel>
))}
</RadioGroup>
</CardContent>
</Card>
)
}
export function NotificationsCard() {
return (
<Card size="sm">
<CardHeader>
<CardTitle>Notifications</CardTitle>
<CardDescription>Changes save as you switch.</CardDescription>
</CardHeader>
<CardContent>
<FieldGroup className="gap-3">
{alerts.map((alert) => (
<Field key={alert.id} orientation="horizontal">
<FieldLabel
htmlFor={`showcase-${alert.id}`}
className="flex-1 font-normal"
>
{alert.title}
</FieldLabel>
<Switch id={`showcase-${alert.id}`} defaultChecked={alert.on} />
</Field>
))}
</FieldGroup>
</CardContent>
</Card>
)
}
function UsageCard() {
return (
<Card size="sm">
<CardHeader>
<CardTitle className="flex items-center gap-2">
Usage <Badge variant="success">On track</Badge>
</CardTitle>
<CardDescription>Resets on the first of the month.</CardDescription>
</CardHeader>
<CardContent className="flex flex-col gap-2">
<div className="flex justify-between text-sm">
<span>Build minutes</span>
<span className="text-muted-foreground tabular-nums">
3,120 of 6,000
</span>
</div>
<Progress value={52} aria-label="Build minutes used" />
</CardContent>
<CardFooter className="justify-end">
<Button variant="outline" size="sm">
Manage plan
</Button>
</CardFooter>
</Card>
)
}
function AppearanceCard() {
return (
<Card size="sm">
<CardHeader>
<CardTitle>Appearance</CardTitle>
<CardDescription>How the editor looks on this device.</CardDescription>
</CardHeader>
<CardContent className="flex flex-col gap-5">
{/* One choice of three with nothing to switch between: a toggle
group, not tabs. */}
<ToggleGroup
variant="outline"
spacing={0}
defaultValue={["system"]}
aria-label="Theme"
className="w-full"
>
<ToggleGroupItem value="light" className="flex-1">
Light
</ToggleGroupItem>
<ToggleGroupItem value="dark" className="flex-1">
Dark
</ToggleGroupItem>
<ToggleGroupItem value="system" className="flex-1">
System
</ToggleGroupItem>
</ToggleGroup>
<div className="flex items-center gap-3 text-muted-foreground">
<MinusIcon className="size-4 shrink-0" aria-hidden="true" />
<Slider defaultValue={60} aria-label="Text size" />
<PlusIcon className="size-4 shrink-0" aria-hidden="true" />
</div>
</CardContent>
</Card>
)
}
function VerifyCard() {
return (
<Card size="sm">
<CardHeader>
<CardTitle>Two-step verification</CardTitle>
<CardDescription>
Enter the code from your authenticator.
</CardDescription>
</CardHeader>
<CardContent className="flex flex-col items-start gap-4">
<InputOTP maxLength={6} aria-label="Verification code">
<InputOTPGroup>
<InputOTPSlot index={0} />
<InputOTPSlot index={1} />
<InputOTPSlot index={2} />
</InputOTPGroup>
<InputOTPSeparator />
<InputOTPGroup>
<InputOTPSlot index={3} />
<InputOTPSlot index={4} />
<InputOTPSlot index={5} />
</InputOTPGroup>
</InputOTP>
<Button size="sm">Verify</Button>
</CardContent>
</Card>
)
}
const column = "flex flex-col gap-4"
/**
* A wall of components in their default theme: what the system looks like
* before anyone has styled anything. One column on a phone, three on a desk.
*/
export default function LandingShowcase() {
return (
<div className="grid gap-4 @2xl:grid-cols-2 @5xl:grid-cols-3">
<div className={column}>
<AccountCard />
<UsageCard />
</div>
<div className={`${column} @max-2xl:hidden`}>
<TeamCard />
<PlanCard />
<Alert variant="success">
<CircleCheckIcon />
<AlertTitle>Deployment ready</AlertTitle>
<AlertDescription>
Production now serves the build from main.
</AlertDescription>
</Alert>
</div>
<div className={`${column} @max-5xl:hidden`}>
<NotificationsCard />
<AppearanceCard />
<VerifyCard />
</div>
</div>
)
}<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80">
<rect width="80" height="80" fill="#e4eaff"/>
<circle cx="40" cy="31" r="14" fill="#8ea6ff"/>
<path d="M12 80c0-15.5 12.5-26 28-26s28 10.5 28 26z" fill="#8ea6ff"/>
</svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80">
<rect width="80" height="80" fill="#fdebe0"/>
<circle cx="40" cy="31" r="14" fill="#f0a072"/>
<path d="M12 80c0-15.5 12.5-26 28-26s28 10.5 28 26z" fill="#f0a072"/>
</svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80">
<rect width="80" height="80" fill="#dcf2ef"/>
<circle cx="40" cy="31" r="14" fill="#6cbdb3"/>
<path d="M12 80c0-15.5 12.5-26 28-26s28 10.5 28 26z" fill="#6cbdb3"/>
</svg>import type { Metadata } from "next"
import LandingBento from "@/components/landing-bento/landing-bento"
export const metadata: Metadata = {
title: "Landing page: bento",
description: "A two-tone headline and a bento grid where every feature is shown with the thing itself.",
}
export default function LandingBentoPage() {
return <LandingBento />
}