Build a PDF Report Generator
Build a system that generates professional PDF reports from data — invoices, analytics summaries, or client reports. Automate the tedious work of report creation.
Why automated report generation matters
Every business generates reports. Monthly analytics summaries. Client status updates. Financial statements. Invoice batches. These reports follow consistent templates but require fresh data each time. Manually creating them means copying numbers into a template, adjusting formatting, exporting to PDF, and repeating for every client or time period. A single monthly report might take 30 minutes. Multiply that by 20 clients and you have lost an entire day to copy-paste work every month. Automated report generation eliminates this entirely. You define the template once, connect it to your data source, and generate reports on demand or on a schedule. The output is a professional PDF that looks hand-crafted but was generated in seconds. We will build a report generator that can produce analytics reports from JSON data, but the same architecture works for invoices, proposals, contracts, or any document that combines a fixed template with variable data. Create the project: `mkdir ~/projects/pdf-generator && cd ~/projects/pdf-generator && git init && claude`. Tell Claude Code: Create a Node.js project with TypeScript that generates professional PDF reports. We need a template system for defining report layouts, a data ingestion layer that reads JSON or CSV, and a PDF rendering engine. Use @react-pdf/renderer for the PDF generation. Start with the project structure.
Designing the report template
The template defines how your report looks — headers, sections, tables, charts, and styling. Ask Claude Code: Create a PDF report template for a monthly analytics report. The template should include a cover page with the company logo placeholder, report title, date range, and client name. Then a summary section with 4 KPI boxes showing total visitors, conversion rate, revenue, and growth percentage. Then a detailed metrics table with columns for metric name, current value, previous value, and percentage change. Then a page break followed by a trends section with placeholder for a chart. Then a footer on every page with page numbers and the generation date. Use @react-pdf/renderer components and style everything to look professional with a clean sans-serif font and a blue accent color. Claude Code will create React components that render to PDF instead of to the browser. The @react-pdf/renderer library uses a subset of CSS properties applied via a StyleSheet object. The template components accept data as props, so the same template produces different reports depending on the data passed in. Review the template by generating a test PDF: `npm run generate-test`. Open the PDF and check the layout. Common issues at this stage include text overflowing table cells, page breaks splitting content awkwardly, and fonts not loading. Tell Claude Code about any issues and it will fix them. The template is your most important asset — spend time getting it right because every report you generate uses it.
Data ingestion and transformation
Reports need data. Build a flexible data ingestion layer. Ask Claude Code: Create a data ingestion module that reads report data from JSON files. The module should validate the data against a TypeScript interface, calculate derived metrics like percentage changes and totals, handle missing or invalid values gracefully with fallback defaults, and transform raw data into the shape the report template expects. Define a clear interface: the input is raw data from your analytics tool or database export. The output is a structured object that maps directly to template components. For example, raw data might have daily page view counts for 30 days. The transformation calculates the total, the daily average, the comparison with the previous period, and the percentage change. Ask Claude Code to also support CSV input: Add a CSV parser that reads analytics exports from common tools like Google Analytics or Stripe. Map CSV columns to our report data interface. Handle different date formats and number formats. The transformation layer is where you add business logic. If revenue grew more than 20 percent, add a highlight. If a metric declined, show it in red. If data is missing for certain days, interpolate or show a note. Ask Claude Code to implement these rules. Test with sample data files. Create a sample-data/ directory with a few JSON files representing different scenarios: a great month with all metrics up, a poor month with declining metrics, and a month with some missing data. Generate reports from each and verify the output handles all cases correctly.
Professional styling and branding
A report that looks generic undermines trust. Make it look like it came from a design team. Ask Claude Code: Enhance the report styling with these improvements. Add a branded header with a colored bar across the top of each page. Use a consistent color palette: dark navy for headings, medium grey for body text, blue for positive metrics, and red for negative metrics. Style the KPI boxes with large bold numbers, a small label below, and a colored arrow indicator showing the direction of change. Format the metrics table with alternating row backgrounds, bold headers, and proper alignment where numbers are right-aligned and text is left-aligned. Add a professional cover page with centered content and generous whitespace. For typography, @react-pdf/renderer supports custom fonts. Ask Claude Code: Register the Inter font family by downloading the font files and registering them with Font.register. Use Inter Regular for body text, Inter Semibold for headings, and Inter Bold for KPI numbers. Ensure consistent font sizes: 24pt for report title, 18pt for section headings, 12pt for body text, 10pt for table content, and 8pt for footer text. Generate a report and compare it against professional reports you admire. The goal is that someone receiving this PDF would assume it was designed by a professional, not generated by code. Small details matter: consistent margins, proper spacing between sections, and elegant page breaks that never leave orphaned headers at the bottom of a page.
Bulk generation and parameterization
The real power of automated reports is generating many at once. Ask Claude Code: Add a bulk generation feature. Create a CLI command that takes a directory of JSON data files and generates a PDF report for each one. Show a progress bar during generation. Name each output file based on the client name and date range from the data. Support a --output-dir flag for specifying where PDFs are saved. Example usage: `npm run generate -- --input data/ --output reports/`. The command should read all JSON files from the input directory, validate each one, generate the PDF, save it to the output directory, and report any errors without stopping the batch. Test with 10 sample data files. The batch should complete in under 30 seconds. If it is slower, ask Claude Code to optimize — PDF generation can be parallelized. Add parameterization for template variants: tell Claude Code to support a --template flag that selects between different report layouts. Create a summary template with just the cover page and KPIs as a one-page overview, a detailed template with the full report including all tables and charts, and an executive template with large text and minimal data for C-level readers. Each template reuses the same components but arranges them differently. This means one data file can produce three different reports for different audiences. Add a --format flag that supports PDF and HTML output — HTML reports can be emailed directly while PDFs can be attached.
API endpoint for on-demand generation
Sometimes you need reports generated on the fly from a web application. Ask Claude Code: Add an Express API endpoint at POST /api/generate-report that accepts JSON data in the request body, validates it, generates a PDF report, and returns the PDF as a downloadable file response. Add proper error handling for invalid data. Rate limit the endpoint to 10 requests per minute. The endpoint should accept an optional template parameter to select between summary, detailed, and executive templates. Test with curl: `curl -X POST -H 'Content-Type: application/json' -d @sample-data/client-a.json http://localhost:3000/api/generate-report --output report.pdf`. Open report.pdf and verify it generated correctly. For integration into a web application, ask Claude Code: Create a simple web page at the root URL that shows a form where users can paste JSON data or upload a JSON file, select a template, and click Generate. Show a loading spinner while the PDF is being generated, then provide a download link. This gives non-technical team members a way to generate reports without using the command line. Add authentication to the API endpoint so only authorized users can generate reports. For a simple implementation, use an API key passed in the Authorization header. For a production system, integrate with your existing authentication provider. Store generated reports in a database or file storage so they can be retrieved later without regenerating.
Scheduling and automation
The ultimate goal is reports that generate themselves. Ask Claude Code: Add a scheduling system that generates reports automatically. Create a configuration file at config/schedules.json where each entry specifies a client name, data source URL or file path, template to use, schedule as a cron expression, and recipients as a list of email addresses. Build a scheduler that reads this configuration and triggers report generation at the specified times. Use node-cron for the scheduling and Resend for email delivery. Each scheduled run should fetch the latest data from the source, generate the report, email it to recipients as a PDF attachment, and log the result including success or failure and generation time. Test the scheduler by setting a schedule to run every minute, watching it generate and send a report, and then updating the schedule to the real cadence. Common schedules are weekly on Monday morning and monthly on the first business day. Add error handling for when data sources are unavailable, email delivery fails, or PDF generation errors occur. The scheduler should retry failed reports up to 3 times with increasing delays. Send an alert email to the admin if a report fails all retries. After everything is working, you have a complete automated reporting system: define your templates, connect your data sources, set your schedules, and reports flow to the right people at the right time without any manual intervention.
AI Automation Fundamentals
This guide is hands-on and practical. The full curriculum covers the conceptual foundations in depth with structured lessons and quizzes.
Go to lesson