Development · Tip
Next.js PDF Invoice Route Handler Pattern
Server-side PDF generation pattern for Next.js App Router using React streaming
A clean production recipe for generating and serving PDF invoices via a Next.js route handler. It combines Zod query validation, database fetching, and server-side React PDF rendering into a streamed binary response with proper attachment headers.
How it works
How to render a PDF invoice using Next.js (file: api/download/invoice/route.tsx):
- import { PdfTemplate, renderToStream } from "@midday/invoice"; getInvoiceQuery from @midday/supabase/queries; createClient from @midday/supabase/server; NextRequest from next/server; z from zod.
- export const preferredRegion = ["fra1", "sfo1", "iad1"];
- paramsSchema = z.object({ id: z.string().uuid(), size: z.enum(["letter","a4"]).default("a4"), preview: z.boolean().default(false) });
- GET(req: NextRequest): create admin supabase client; parse URL search params with paramsSchema.safeParse; return 400 "Invalid parameters" on failure.
- Fetch invoice via getInvoiceQuery(supabase, id); return 404 "Invoice not found" if missing.
- const stream = await renderToStream(<PdfTemplate {...data} size={size} />); convert to blob via new Response(stream).blob().
- Headers: Content-Type application/pdf, Cache-Control no-store,max-age=0; if not preview, Content-Disposition attachment with filename `${data.invoice_number}.pdf`.
- Return new Response(blob, { headers }).
Pattern: Zod validation → query → React PDF template rendered to stream → blob response with download/preview headers.
What it's for
- Generate and download PDF invoices on demand in a Next.js application
- Stream rendered React PDF templates directly to the client without saving files to disk
- Support both inline PDF previews and forced file downloads via query parameters
Key points
- Schema validation with Zod for invoice ID, page size, and preview toggle
- Configured edge/server preferred regions for reliable rendering
- Direct streaming of React PDF templates using renderToStream
- Conditional Content-Disposition headers for inline preview versus attachment download
- No-cache control headers to prevent stale financial document downloads
Pricing
Free
Details
- Type
- Tip
- Category
- Development
- Topic
- Code Snippets
- Open source
- No
- Platforms
- Web, API
- For
- Next.js and full-stack React developers
- Alternative to
- Puppeteer PDF generation, DocuGenerate API
- Tags
- nextjs, react pdf, zod, pdf generation, typescript, route handlers
Why it was saved
- @pontusab: A concise, production-shaped recipe for server-side PDF generation in Next.js: typed request validation, region preference, streaming, and download/preview headers.
Related
Open-source React PDF template and Next.js route for rendering invoices
Full-stack SaaS starter with Next.js 15, Convex, and Clerk Billing
Render structured JSON specifications into PDFs using React PDF
Open-source TypeScript and React component library for building AI chat interfaces
Open-source file upload library for React connecting to S3-compatible storage
Open-source CRM data grid and interface template built with Next.js and shadcn/ui
Updated