Back to Blog
·8 min read

Building an Invoice Generator with Next.js & Supabase

Next.jsSupabaseTailwind CSSPDF

Managing invoices manually is tedious and error-prone. I built an Invoice Generator that lets users create, manage, and export invoices as PDFs — all powered by Next.js, Tailwind CSS, and Supabase.

Key Functionalities

  • Invoice CRUD — Create, edit, duplicate, and delete invoices with a clean, intuitive UI
  • PDF Export — Generate professional PDF invoices with proper formatting, logos, and line items
  • Authentication — Secure user accounts via Supabase Auth so each user sees only their own invoices
  • Dynamic Line Items — Add, remove, and reorder invoice items with automatic subtotal, tax, and total calculations
  • Responsive Design — Fully usable on mobile and desktop with Tailwind CSS

Problem: PDF Generation on the Client

The first challenge was generating PDFs. Server-side solutions like Puppeteer were too heavy for a Vercel deployment. I opted for a client-side approach using html2canvas combined with jsPDF. The tricky part was getting the invoice layout to render identically in the PDF — CSS Grid and Flexbox don't always translate perfectly to canvas. I solved this by creating a hidden "print-ready" version of the invoice with fixed pixel widths and inline styles that canvas could reliably capture.

Problem: Supabase Row-Level Security

Supabase's Row-Level Security (RLS) is powerful but initially confusing. My invoices weren't showing up after creation because I had forgotten to add a SELECT policy alongside the INSERT policy. The fix was straightforward — define policies for each operation (SELECT, INSERT, UPDATE, DELETE) filtered by auth.uid() = user_id. Lesson learned: always test every CRUD operation after setting up RLS.

Problem: Dynamic Form State Management

Handling a dynamic list of line items with React state was tricky. Adding and removing items while keeping calculations in sync caused stale state bugs. I solved this by using useReducer instead of multiple useState hooks, which gave me predictable state transitions and made the auto-calculation logic (subtotal, tax, discount, total) much cleaner.

Key Takeaways

Supabase is an excellent choice for apps that need auth + database without a custom backend. The combination of Next.js for the frontend and Supabase for the backend let me ship a production-ready app fast. The biggest lesson: always prototype your PDF output early — it saves hours of layout debugging later.

Try it out at the live demo or check the source code.