Skip to content
All Taste components

Templates

SaaS product page

A complete landing page for an invoicing app, with a product screenshot hero, bento features and three-tier pricing.

Nav · hero with app screenshot · logos · bento features · how it works · pricing with monthly/yearly · testimonials · FAQ · CTA · footer

NewRecurring invoices for retainers

Send the invoice. We’ll chase the payment.

Ledgerleaf makes GST-ready invoices in a minute, lets clients pay by UPI or card, and follows up until the money is in.

Free for 5 invoices a month · No card needed

Used by 3,200 studios, agencies and consultants

  • Halcyon Labs
  • Tinkerbox
  • Moonrise
  • Arcadia Print
  • Kiln & Co
  • Parallel

Features

Everything between “work done” and “money in”

Invoices that look like your business

Your logo, your colours, your terms. Line items, discounts and GST worked out as you type.

INV-2041 · Bloom & CoPaid
Brand identity, phase 2₹38,000
Packaging files₹3,100
IGST 18%₹7,400
Total₹48,500

Reminders that chase for you

Polite emails on a schedule you set.

  1. Invoice sent1 Oct
  2. Friendly nudge8 Oct
  3. Due today15 Oct

GST, done right

The split is picked from the place of supply.

CGST 9%SGST 9%IGST 18%

Know your cash flow

What came in, what is owed and what lands next month.

Paid the way clients like

One link on every invoice, every method behind it.

UPICardsNet bankingBank transferInternational cards

Clients abroad, rupees at home

Bill in 14 currencies and see the rupee value the day it is paid.

  • Fern & Field · London£1,200
  • Okto GmbH · Berlin€2,450

How it works

Set up before your coffee cools

  1. Add your business

    Your GSTIN, logo and bank details. We fill the rest from your GSTIN.

  2. Send the first invoice

    Pick a template, add line items and send it by email or a link.

  3. Get paid and reconciled

    Payments match their invoices on their own, ready for your accountant.

Pricing

Simple plans, priced in rupees

Solo

₹0₹0free forever

For freelancers sending a few invoices a month.

Start free
  • 5 invoices a month
  • UPI and card payments
  • GST-ready templates

Studio

Most popular
₹666₹799/ month

For small teams that bill every week.

Try Studio free
  • Unlimited invoices
  • Automatic reminders
  • Recurring billing
  • 3 team members

Agency

₹1,833₹2,199/ month

For agencies with many clients and currencies.

Talk to us
  • Everything in Studio
  • 14 currencies
  • Approvals and roles
  • Priority support

Prices exclude 18% GST. Cancel any time.

Customers

Fewer reminders, faster payments

“We used to spend Friday afternoons chasing payments. Now the reminders do it and we hear about it when the money lands.”
RMRitika MenonFounder, Haldi Studio
“Our accountant stopped asking for spreadsheets. The GST report is just there at the end of the month.”
ABArjun BhatPartner, Kite & Kin
“Clients pay from the invoice link by UPI. Our average wait went from 34 days to 9.”
LFLeah FernandesOperations, Bloom & Co

FAQ

Questions, answered

Something else? Write to help@ledgerleaf.in and a person replies within a working day.

Is Ledgerleaf GST compliant?

Yes. Invoices carry your GSTIN, HSN or SAC codes and the right CGST, SGST or IGST split, and the monthly report matches the GSTR-1 layout.

How do my clients pay?

Every invoice has a payment link. Clients pay by UPI, card, net banking or bank transfer, and the invoice is marked paid on its own.

Can I bring my old invoices?

Import a CSV from your spreadsheet or accounting tool. Numbering carries on from your last invoice.

What happens when my trial ends?

You move to the free Solo plan unless you pick a paid one. Nothing is deleted.

Your next invoice could be paid by Friday

Start free, send five invoices this month, and upgrade only when you need more.

"use client";
import { useState } from "react";
import { ArrowRight, Check, Menu, Star } from "lucide-react";
import { cn } from "@/lib/utils";

const invoices = [
  { client: "Bloom & Co", number: "INV-2041", amount: "₹48,500", status: "Paid" },
  { client: "Haldi Studio", number: "INV-2040", amount: "₹1,12,000", status: "Due in 6 days" },
  { client: "Northpoint Tea", number: "INV-2039", amount: "₹36,250", status: "Overdue" },
  { client: "Kite & Kin", number: "INV-2038", amount: "₹74,800", status: "Paid" },
];

const steps = [
  { title: "Add your business", body: "Your GSTIN, logo and bank details. We fill the rest from your GSTIN." },
  { title: "Send the first invoice", body: "Pick a template, add line items and send it by email or a link." },
  { title: "Get paid and reconciled", body: "Payments match their invoices on their own, ready for your accountant." },
];

const plans = [
  { name: "Solo", monthly: "₹0", yearly: "₹0", blurb: "For freelancers sending a few invoices a month.", cta: "Start free", features: ["5 invoices a month", "UPI and card payments", "GST-ready templates"] },
  { name: "Studio", monthly: "₹799", yearly: "₹666", blurb: "For small teams that bill every week.", cta: "Try Studio free", popular: true, features: ["Unlimited invoices", "Automatic reminders", "Recurring billing", "3 team members"] },
  { name: "Agency", monthly: "₹2,199", yearly: "₹1,833", blurb: "For agencies with many clients and currencies.", cta: "Talk to us", features: ["Everything in Studio", "14 currencies", "Approvals and roles", "Priority support"] },
];

const quotes = [
  { quote: "We used to spend Friday afternoons chasing payments. Now the reminders do it.", name: "Ritika Menon", role: "Founder, Haldi Studio" },
  { quote: "Our accountant stopped asking for spreadsheets. The GST report is just there.", name: "Arjun Bhat", role: "Partner, Kite & Kin" },
  { quote: "Clients pay from the invoice link by UPI. Our average wait went from 34 days to 9.", name: "Leah Fernandes", role: "Operations, Bloom & Co" },
];

const faqs = [
  { q: "Is Ledgerleaf GST compliant?", a: "Yes. Invoices carry your GSTIN, HSN or SAC codes and the right CGST, SGST or IGST split." },
  { q: "How do my clients pay?", a: "Every invoice has a payment link: UPI, card, net banking or bank transfer." },
  { q: "Can I bring my old invoices?", a: "Import a CSV from your spreadsheet or accounting tool. Numbering carries on." },
  { q: "What happens when my trial ends?", a: "You move to the free Solo plan unless you pick a paid one. Nothing is deleted." },
];

const footer = [
  { title: "Product", links: ["Invoices", "Payments", "Reminders", "Reports"] },
  { title: "Company", links: ["About", "Careers", "Blog", "Contact"] },
  { title: "Help", links: ["Guides", "GST basics", "Status", "Security"] },
];

function Container({ className, children }: { className?: string; children: React.ReactNode }) {
  return <div className={cn("mx-auto w-full max-w-6xl px-5 sm:px-8", className)}>{children}</div>;
}

function SectionHead({ eyebrow, title, align = "center" }: { eyebrow: string; title: string; align?: "center" | "left" }) {
  return (
    <div className={cn("mb-12 grid gap-3", align === "center" ? "mx-auto max-w-2xl text-center" : "max-w-2xl")}>
      <p className="text-sm font-medium text-primary">{eyebrow}</p>
      <h2 className="text-balance text-3xl font-semibold tracking-tight sm:text-4xl">{title}</h2>
    </div>
  );
}

function Logo() {
  return (
    <a href="/" className="flex items-center gap-2 font-semibold tracking-tight">
      <span className="size-6 rounded-sm bg-primary" aria-hidden /> Ledgerleaf
    </a>
  );
}

function Header() {
  return (
    <header className="border-b border-border">
      <Container className="flex h-16 items-center gap-8">
        <Logo />
        <nav aria-label="Main" className="hidden gap-6 text-sm text-fg-muted md:flex">
          {["Product", "Pricing", "Customers", "Help"].map((l) => <a key={l} href="#" className="hover:text-fg">{l}</a>)}
        </nav>
        <div className="ml-auto flex items-center gap-2">
          <a href="#" className="hidden rounded px-3 py-2 text-sm hover:bg-surface-2 sm:block">Sign in</a>
          <a href="#" className="rounded bg-primary px-4 py-2 text-sm font-medium text-primary-fg hover:bg-primary-hover">Start free</a>
          <button type="button" aria-label="Open menu" className="rounded p-2 hover:bg-surface-2 md:hidden"><Menu className="size-5" /></button>
        </div>
      </Container>
    </header>
  );
}

function Hero() {
  return (
    <section className="relative overflow-hidden pt-16 text-center sm:pt-20">
      <Container>
        <h1 className="mx-auto max-w-3xl text-balance text-4xl font-semibold tracking-tight sm:text-6xl">
          Send the invoice. We’ll chase the payment.
        </h1>
        <p className="mx-auto mt-5 max-w-xl text-lg text-fg-muted">
          GST-ready invoices in a minute, paid by UPI or card, followed up until the money is in.
        </p>
        <div className="mt-8 flex flex-wrap justify-center gap-3">
          <a href="#" className="inline-flex h-11 items-center gap-2 rounded bg-primary px-5 font-medium text-primary-fg hover:bg-primary-hover">Start free <ArrowRight className="size-4" /></a>
          <a href="#" className="inline-flex h-11 items-center rounded border border-border-strong px-5 font-medium hover:bg-surface">Book a demo</a>
        </div>
        <p className="mt-3 text-sm text-fg-subtle">Free for 5 invoices a month · No card needed</p>
        <div className="mx-auto mt-14 max-w-5xl rounded-t-xl border border-b-0 border-border bg-surface-2 p-2 pb-0">
          <div className="rounded-t-lg border border-b-0 border-border bg-bg p-4 text-left sm:p-6">
            <div className="mb-4 flex items-center justify-between">
              <p className="text-lg font-semibold">Invoices</p>
              <span className="rounded bg-primary px-3 py-1.5 text-sm text-primary-fg">New invoice</span>
            </div>
            <table className="w-full text-sm">
              <thead className="text-left text-xs text-fg-subtle">
                <tr><th className="py-2 font-medium">Client</th><th className="hidden py-2 font-medium sm:table-cell">Number</th><th className="py-2 text-right font-medium">Amount</th><th className="py-2 pl-4 font-medium">Status</th></tr>
              </thead>
              <tbody>
                {invoices.map((i) => (
                  <tr key={i.number} className="border-t border-border">
                    <td className="py-2.5">{i.client}</td>
                    <td className="hidden py-2.5 text-fg-muted sm:table-cell">{i.number}</td>
                    <td className="py-2.5 text-right tabular-nums">{i.amount}</td>
                    <td className="py-2.5 pl-4"><span className={cn("rounded-full px-2 py-0.5 text-xs font-medium", i.status === "Paid" ? "bg-success-soft text-success-fg" : i.status === "Overdue" ? "bg-danger-soft text-danger-fg" : "bg-warning-soft text-warning-fg")}>{i.status}</span></td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
      </Container>
    </section>
  );
}

function Logos() {
  return (
    <section aria-label="Customers" className="bg-surface py-12 text-center">
      <Container>
        <p className="text-sm text-fg-subtle">Used by 3,200 studios, agencies and consultants</p>
        <ul className="mt-6 flex flex-wrap justify-center gap-x-12 gap-y-4 text-lg font-semibold tracking-tight text-fg-subtle">
          {["Halcyon Labs", "Tinkerbox", "Moonrise", "Arcadia Print", "Kiln & Co", "Parallel"].map((l) => <li key={l}>{l}</li>)}
        </ul>
      </Container>
    </section>
  );
}

function Features() {
  return (
    <section className="py-20 sm:py-24">
      <Container>
        <SectionHead eyebrow="Features" title="Everything between “work done” and “money in”" />
        <div className="grid gap-4 md:grid-cols-6">
          <article className="rounded-xl border border-border bg-primary-soft p-6 md:col-span-4">
            <h3 className="font-semibold">Invoices that look like your business</h3>
            <p className="mt-1.5 text-sm text-fg-muted">Your logo, colours and terms. GST worked out as you type.</p>
          </article>
          <article className="rounded-xl border border-border p-6 md:col-span-2">
            <h3 className="font-semibold">Reminders that chase for you</h3>
            <p className="mt-1.5 text-sm text-fg-muted">Polite emails on a schedule you set.</p>
          </article>
          <article className="rounded-xl border border-border p-6 md:col-span-2">
            <h3 className="font-semibold">GST, done right</h3>
            <p className="mt-1.5 text-sm text-fg-muted">CGST, SGST or IGST from the place of supply.</p>
          </article>
          <article className="rounded-xl border border-border p-6 md:col-span-4">
            <h3 className="font-semibold">Know your cash flow</h3>
            <p className="mt-1.5 text-sm text-fg-muted">What came in, what is owed and what lands next month.</p>
          </article>
          <article className="rounded-xl border border-border p-6 md:col-span-3">
            <h3 className="font-semibold">Paid the way clients like</h3>
            <p className="mt-1.5 text-sm text-fg-muted">UPI, cards, net banking and bank transfer behind one link.</p>
          </article>
          <article className="rounded-xl border border-border p-6 md:col-span-3">
            <h3 className="font-semibold">Clients abroad, rupees at home</h3>
            <p className="mt-1.5 text-sm text-fg-muted">Bill in 14 currencies and see the rupee value when paid.</p>
          </article>
        </div>
      </Container>
    </section>
  );
}

function HowItWorks() {
  return (
    <section className="bg-surface py-20 sm:py-24">
      <Container>
        <SectionHead eyebrow="How it works" title="Set up before your coffee cools" align="left" />
        <ol className="grid gap-8 md:grid-cols-3">
          {steps.map((s, i) => (
            <li key={s.title} className="grid gap-2">
              <span className="grid size-9 place-items-center rounded-full bg-fg text-sm font-semibold text-bg">{i + 1}</span>
              <h3 className="mt-3 font-semibold">{s.title}</h3>
              <p className="text-sm text-fg-muted">{s.body}</p>
            </li>
          ))}
        </ol>
      </Container>
    </section>
  );
}

function Pricing() {
  const [yearly, setYearly] = useState(true);
  return (
    <section className="py-20 sm:py-24">
      <Container>
        <SectionHead eyebrow="Pricing" title="Simple plans, priced in rupees" />
        <div role="tablist" aria-label="Billing period" className="mx-auto -mt-4 mb-10 flex w-fit gap-0.5 rounded-lg bg-surface-2 p-1">
          {[false, true].map((y) => (
            <button key={String(y)} type="button" role="tab" aria-selected={yearly === y} onClick={() => setYearly(y)}
              className="rounded px-3 py-1.5 text-sm font-medium text-fg-muted aria-selected:bg-bg aria-selected:text-fg aria-selected:shadow-sm">
              {y ? "Yearly · 2 months free" : "Monthly"}
            </button>
          ))}
        </div>
        <div className="mx-auto grid max-w-md gap-4 lg:max-w-none lg:grid-cols-3">
          {plans.map((p) => (
            <article key={p.name} className={cn("grid gap-5 rounded-xl border p-7", p.popular ? "border-fg bg-fg text-bg shadow-xl" : "border-border bg-bg")}>
              <div className="flex items-center justify-between">
                <h3 className="font-semibold">{p.name}</h3>
                {p.popular && <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="flex items-baseline gap-1.5">
                <span className="text-5xl font-semibold tracking-tight tabular-nums">{yearly ? p.yearly : p.monthly}</span>
                <span className={cn("text-sm", p.popular ? "text-bg" : "text-fg-subtle")}>/ month</span>
              </p>
              <p className={cn("text-sm", p.popular ? "text-bg" : "text-fg-muted")}>{p.blurb}</p>
              <a href="#" className={cn("flex h-11 items-center justify-center rounded font-medium", p.popular ? "bg-primary text-primary-fg hover:bg-primary-hover" : "border border-border-strong hover:bg-surface")}>{p.cta}</a>
              <ul className="grid gap-2.5 border-t border-border pt-5 text-sm">
                {p.features.map((f) => <li key={f} className="flex gap-2.5"><Check className="mt-0.5 size-4 shrink-0 text-primary" />{f}</li>)}
              </ul>
            </article>
          ))}
        </div>
        <p className="mt-5 text-center text-sm text-fg-subtle">Prices exclude 18% GST. Cancel any time.</p>
      </Container>
    </section>
  );
}

function Testimonials() {
  return (
    <section className="bg-surface py-20 sm:py-24">
      <Container>
        <SectionHead eyebrow="Customers" title="Fewer reminders, faster payments" />
        <div className="grid gap-4 md:grid-cols-3">
          {quotes.map((t) => (
            <figure key={t.name} className="grid content-between gap-5 rounded-lg border border-border bg-bg p-6">
              <div className="flex gap-0.5 text-primary" aria-label="5 out of 5 stars">{[0, 1, 2, 3, 4].map((i) => <Star key={i} className="size-4 fill-current" />)}</div>
              <blockquote>“{t.quote}”</blockquote>
              <figcaption className="text-sm"><p className="font-medium">{t.name}</p><p className="text-fg-subtle">{t.role}</p></figcaption>
            </figure>
          ))}
        </div>
      </Container>
    </section>
  );
}

function Faq() {
  return (
    <section className="py-20 sm:py-24">
      <Container className="grid gap-10 lg:grid-cols-[2fr_3fr] lg:gap-16">
        <div className="grid content-start gap-3">
          <p className="text-sm font-medium text-primary">FAQ</p>
          <h2 className="text-3xl font-semibold tracking-tight sm:text-4xl">Questions, answered</h2>
          <p className="text-fg-muted">Something else? Write to help@ledgerleaf.in.</p>
        </div>
        <div className="border-t border-border">
          {faqs.map((f, i) => (
            <details key={f.q} open={i === 0} className="group border-b border-border">
              <summary className="flex cursor-pointer list-none items-center justify-between gap-4 py-4 font-medium">{f.q}<span className="text-fg-subtle group-open:rotate-180" aria-hidden>⌄</span></summary>
              <p className="pb-5 pr-8 text-sm text-fg-muted">{f.a}</p>
            </details>
          ))}
        </div>
      </Container>
    </section>
  );
}

function Cta() {
  return (
    <section className="pb-20 sm:pb-24">
      <Container>
        <div className="grid justify-items-center gap-4 rounded-xl bg-primary px-6 py-16 text-center text-primary-fg">
          <h2 className="text-balance text-3xl font-semibold tracking-tight sm:text-4xl">Your next invoice could be paid by Friday</h2>
          <p className="max-w-lg">Start free, send five invoices this month, and upgrade only when you need more.</p>
          <a href="#" className="mt-2 inline-flex h-11 items-center gap-2 rounded bg-bg px-5 font-medium text-fg">Start free <ArrowRight className="size-4" /></a>
        </div>
      </Container>
    </section>
  );
}

function Footer() {
  return (
    <footer className="border-t border-border pb-8 pt-16">
      <Container>
        <div className="grid grid-cols-2 gap-8 md:grid-cols-[1.6fr_1fr_1fr_1fr]">
          <div className="col-span-2 grid content-start gap-3 md:col-span-1"><Logo /><p className="max-w-xs text-sm text-fg-muted">Invoicing and payments for small studios, made in Bengaluru.</p></div>
          {footer.map((c) => (
            <nav key={c.title} aria-label={c.title}>
              <h2 className="mb-3 text-sm font-medium text-fg-subtle">{c.title}</h2>
              <ul className="grid gap-2.5 text-sm text-fg-muted">{c.links.map((l) => <li key={l}><a href="#" className="hover:text-fg">{l}</a></li>)}</ul>
            </nav>
          ))}
        </div>
        <p className="mt-14 border-t border-border pt-6 text-sm text-fg-subtle">© 2026 Ledgerleaf Software Pvt. Ltd.</p>
      </Container>
    </footer>
  );
}

export default function Page() {
  return (
    <div className="bg-bg font-sans text-fg">
      <Header />
      <main>
        <Hero />
        <Logos />
        <Features />
        <HowItWorks />
        <Pricing />
        <Testimonials />
        <Faq />
        <Cta />
      </main>
      <Footer />
    </div>
  );
}

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