PDF Generation

Generate invoices and reports as PDF files using @react-pdf/renderer.

Generate professional PDF documents from React components in ~10 minutes. Includes a production-ready invoice template.

What's Included

FilePurpose
components/features/pdf-generation/invoice-template.tsxInvoiceDocument component + InvoiceData type

Setup

1

Install dependencies

pnpm add @react-pdf/renderer
2

Create the PDF API route

Create app/api/pdf/invoice/route.ts:

import { renderToBuffer } from "@react-pdf/renderer"
import { NextResponse } from "next/server"
import { getRequiredSession } from "@/lib/auth-utils"
import { InvoiceDocument, type InvoiceData } from "@/components/features/pdf-generation/invoice-template"

export async function GET(req: Request) {
  const session = await getRequiredSession()
  const invoiceId = new URL(req.url).searchParams.get("id")
  if (!invoiceId) return NextResponse.json({ success: false, error: "Invoice ID required" }, { status: 400 })

  const invoiceData: InvoiceData = {
    invoiceNumber: `INV-${invoiceId}`,
    date: new Date().toLocaleDateString("en-US", { year: "numeric", month: "long", day: "numeric" }),
    dueDate: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toLocaleDateString("en-US", { year: "numeric", month: "long", day: "numeric" }),
    company: { name: "Your Company", address: "123 Business St", city: "San Francisco, CA 94102", email: "billing@yourcompany.com" },
    customer: { name: session.user.name ?? "Customer", email: session.user.email ?? "", address: "", city: "" },
    items: [{ description: "Pro Plan — Monthly", quantity: 1, unitPrice: 29, total: 29 }],
    subtotal: 29,
    tax: 0,
    total: 29,
  }

  const buffer = await renderToBuffer(<InvoiceDocument data={invoiceData} />)

  return new NextResponse(buffer, {
    headers: {
      "Content-Type": "application/pdf",
      "Content-Disposition": `attachment; filename="invoice-${invoiceId}.pdf"`,
    },
  })
}
3

Add a download button

"use client"

import { Button } from "@/components/ui/button"
import { Download } from "lucide-react"

export function DownloadInvoiceButton({ invoiceId }: { invoiceId: string }) {
  return (
    <Button onClick={() => window.open(`/api/pdf/invoice?id=${invoiceId}`, "_blank")} variant="outline" size="sm">
      <Download className="mr-2 h-4 w-4" />
      Download Invoice
    </Button>
  )
}

InvoiceData Type

interface InvoiceData {
  invoiceNumber: string
  date: string
  dueDate: string
  company: { name: string; address: string; city: string; email: string }
  customer: { name: string; email: string; address: string; city: string }
  items: Array<{ description: string; quantity: number; unitPrice: number; total: number }>
  subtotal: number
  tax: number
  total: number
  notes?: string
}

Environment Variables

None required.

Verification

  1. Install deps and create the API route
  2. Start dev: pnpm dev
  3. Navigate to /api/pdf/invoice?id=001 (must be authenticated)
  4. A PDF should download with company header, customer details, line items, and totals

Demo Mode — Explore freely. Some actions are restricted. demo@launchfst.dev / demo1234

Get LaunchFst →