Skip to content
All Taste components

Pricing

Pricing — three tiers, joined columns

Three plans in one framed table of columns, the recommended one tinted, with what every plan includes underneath.

3 plans · recommended column · included-in-all row · 1 → 3 columns

Pricing

Pay for the size of your business, not the size of your invoices

Every plan sends unlimited reminders. Change or cancel whenever you like.

Starter

For sole traders sending a few invoices a month.

$0free forever
Start free
  • 10 invoices a month
  • Card and bank payments
  • Automatic reminders
  • 1 user

Growth

Recommended

For small teams who bill every week.

$18per month
Start 14-day trial
  • Unlimited invoices
  • Recurring billing
  • Your logo and colours
  • Late fees added for you
  • 3 users

Business

For companies with several people billing.

$49per month
Start 14-day trial
  • Everything in Growth
  • Approval before sending
  • Client portal
  • Accounting sync
  • 10 users
  • Bank-level encryption
  • No card fees from us
  • Unlimited clients
  • Email support
import { Check, CreditCard, Lock, Mail, Users } from "lucide-react";
import { cn } from "@/lib/utils";

type Plan = { name: string; note: string; price: string; per: string; cta: string; href: string; recommended?: boolean; perks: string[] };

const plans: Plan[] = [
  { name: "Starter", note: "For sole traders sending a few invoices a month.", price: "$0", per: "free forever", cta: "Start free", href: "/signup",
    perks: ["10 invoices a month", "Card and bank payments", "Automatic reminders", "1 user"] },
  { name: "Growth", note: "For small teams who bill every week.", price: "$18", per: "per month", cta: "Start 14-day trial", href: "/signup?plan=growth", recommended: true,
    perks: ["Unlimited invoices", "Recurring billing", "Your logo and colours", "Late fees added for you", "3 users"] },
  { name: "Business", note: "For companies with several people billing.", price: "$49", per: "per month", cta: "Start 14-day trial", href: "/signup?plan=business",
    perks: ["Everything in Growth", "Approval before sending", "Client portal", "Accounting sync", "10 users"] },
];

const included = [
  { icon: Lock, label: "Bank-level encryption" },
  { icon: CreditCard, label: "No card fees from us" },
  { icon: Users, label: "Unlimited clients" },
  { icon: Mail, label: "Email support" },
];

export function PricingJoined() {
  return (
    <section aria-labelledby="pricing-joined-title" className="bg-bg px-5 py-16 font-sans sm:px-10 sm:py-20">
      <div className="mx-auto max-w-6xl">
        <div className="mx-auto max-w-2xl text-center">
          <p className="text-[13px] font-medium text-primary">Pricing</p>
          <h2 id="pricing-joined-title" className="mt-3 text-balance text-3xl font-semibold tracking-tight text-fg sm:text-4xl">
            Pay for the size of your business, not the size of your invoices
          </h2>
          <p className="mt-4 text-base text-fg-muted sm:text-lg">Every plan sends unlimited reminders. Change or cancel whenever you like.</p>
        </div>

        <div className="mt-10 grid overflow-hidden rounded-xl border border-border bg-bg md:grid-cols-3">
          {plans.map((plan) => (
            <article
              key={plan.name}
              aria-label={plan.name + " plan"}
              className={cn(
                "relative flex flex-col gap-6 border-t border-border p-7 first:border-t-0 md:border-l md:border-t-0 md:p-8 md:first:border-l-0",
                plan.recommended && "bg-primary-soft/40 before:absolute before:inset-x-0 before:top-0 before:h-[3px] before:bg-primary",
              )}
            >
              <div>
                <div className="flex items-center justify-between gap-2">
                  <h3 className="text-base font-semibold text-fg">{plan.name}</h3>
                  {plan.recommended && <span className="rounded-full bg-primary-soft px-2 py-0.5 text-xs font-medium text-primary-soft-fg">Recommended</span>}
                </div>
                <p className="mt-1.5 text-[13px] text-fg-subtle">{plan.note}</p>
              </div>
              <p className="flex flex-wrap items-baseline gap-x-2">
                <span className="text-5xl font-semibold tracking-tight tabular-nums text-fg">{plan.price}</span>
                <span className="text-[13px] text-fg-subtle">{plan.per}</span>
              </p>
              <a
                href={plan.href}
                className={cn(
                  "inline-flex h-10 items-center justify-center rounded text-sm font-medium transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
                  plan.recommended ? "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-dashed border-border-strong pt-6 text-[13.5px] 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>

        <ul aria-label="Included in every plan" className="mt-7 flex flex-wrap justify-center gap-x-7 gap-y-2.5 text-[13.5px] text-fg-muted">
          {included.map(({ icon: Icon, label }) => (
            <li key={label} className="inline-flex items-center gap-2"><Icon className="size-4 text-fg-subtle" aria-hidden />{label}</li>
          ))}
        </ul>
      </div>
    </section>
  );
}

The code uses the Taste Tailwind preset. Make yours on the Taste page with Export my system.