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, 28 October 2024: A concise, production-shaped recipe for server-side PDF generation in Next.js: typed request validation, region preference, streaming, and download/preview headers.

Related

  • Midday React PDF Invoice Template

    Open-source React PDF template and Next.js route for rendering invoices

  • Starter.diy

    Full-stack SaaS starter with Next.js 15, Convex, and Clerk Billing

  • @json-render/react-pdf

    Render structured JSON specifications into PDFs using React PDF

  • assistant-ui

    Open-source TypeScript and React component library for building AI chat interfaces

  • Better Upload

    Open-source file upload library for React connecting to S3-compatible storage

  • Gray UI CRM

    Open-source CRM data grid and interface template built with Next.js and shadcn/ui

Updated