Free
For your first few clients
$0$0foreverforever
Start free- 5 invoices a month
- Card and bank payments
- Email reminders
- Fernbill branding on invoices
Pricing
Three plans side by side with a monthly or yearly switch and the recommended plan picked out.
monthly / yearly · highlighted plan · feature lists · 1 → 3 columns
Start free. Upgrade when you have more clients than invoices left.
For your first few clients
For full-time freelancers
For small teams
"use client";
import { useState } from "react";
import { Check } from "lucide-react";
import { cn } from "@/lib/utils";
type Period = "monthly" | "yearly";
const plans = [
{ name: "Free", note: "For your first few clients", price: { monthly: "$0", yearly: "$0" }, cta: "Start free", href: "/signup",
perks: ["5 invoices a month", "Card and bank payments", "Email reminders", "Fernbill branding on invoices"] },
{ name: "Pro", note: "For full-time freelancers", price: { monthly: "$12", yearly: "$10" }, cta: "Start 14-day trial", href: "/signup?plan=pro", featured: true,
perks: ["Unlimited invoices", "Recurring invoices", "Your own reminder schedule", "Your logo and colours", "Late fees, added for you"] },
{ name: "Studio", note: "For small teams", price: { monthly: "$29", yearly: "$24" }, cta: "Talk to us", href: "/contact",
perks: ["Everything in Pro", "5 team seats", "Client portal", "Approval before sending", "Priority support"] },
];
export function PricingThreeTier() {
const [period, setPeriod] = useState<Period>("monthly");
return (
<section aria-labelledby="pricing-title" className="bg-bg font-sans">
<div className="mx-auto max-w-6xl px-4 py-20 sm:px-6">
<div className="mx-auto max-w-xl text-center">
<h2 id="pricing-title" className="text-balance text-3xl font-semibold tracking-tight text-fg sm:text-4xl">Simple pricing that grows with you</h2>
<p className="mt-4 text-base text-fg-muted sm:text-lg">Start free. Upgrade when you have more clients than invoices left.</p>
</div>
<div role="group" aria-label="Billing period" className="mx-auto mt-8 flex w-fit gap-0.5 rounded-lg bg-surface-2 p-[3px]">
{(["monthly", "yearly"] as const).map((p) => (
<button
key={p}
type="button"
aria-pressed={period === p}
onClick={() => setPeriod(p)}
className="inline-flex h-8 items-center gap-1.5 rounded px-3 text-[13px] font-medium capitalize text-fg-muted transition aria-pressed:bg-bg aria-pressed:text-fg aria-pressed:shadow-sm"
>
{p}
{p === "yearly" && <span className="rounded-full bg-primary-soft px-1.5 text-[11px] text-primary-soft-fg">Save 20%</span>}
</button>
))}
</div>
<div className="mt-10 grid gap-4 lg:grid-cols-3">
{plans.map((plan) => {
const free = plan.price.monthly === "$0";
return (
<article
key={plan.name}
aria-label={plan.name + " plan"}
className={cn(
"flex flex-col gap-6 rounded-xl border border-border bg-bg p-6",
plan.featured && "border-primary shadow-xl ring-1 ring-primary",
)}
>
<div>
<div className="flex items-center justify-between gap-2">
<h3 className="text-base font-semibold text-fg">{plan.name}</h3>
{plan.featured && <span className="rounded-full bg-primary-soft px-2 py-0.5 text-xs font-medium text-primary-soft-fg">Most popular</span>}
</div>
<p className="mt-1 text-[13px] text-fg-subtle">{plan.note}</p>
</div>
<p className="flex flex-wrap items-baseline gap-x-1.5">
<span className="text-4xl font-semibold tracking-tight tabular-nums text-fg">{plan.price[period]}</span>
<span className="text-[13px] text-fg-subtle">
{free ? "forever" : period === "yearly" ? "per month, billed yearly" : "per month"}
</span>
</p>
<a
href={plan.href}
className={cn(
"inline-flex h-10 items-center justify-center rounded text-sm font-medium transition",
plan.featured ? "bg-primary text-primary-fg hover:bg-primary-hover" : "border border-border-strong text-fg hover:bg-surface",
)}
>
{plan.cta}
</a>
<ul className="grid gap-2.5 border-t border-border pt-6 text-sm text-fg">
{plan.perks.map((perk) => (
<li key={perk} className="flex items-start gap-2.5">
<Check className="mt-0.5 size-4 shrink-0 text-primary" aria-hidden />
{perk}
</li>
))}
</ul>
</article>
);
})}
</div>
</div>
</section>
);
}
The code uses the Taste Tailwind preset. Make yours on the Taste page with Export my system.