EasyPdf
@easypdf/react is a free, open-source React library for generating PDFs from React components. It works in two modes:
- Visual mode — attach a ref to any element already on screen and download it as a PDF
- Programmatic mode — pass JSX to
createPDForcreatePDFBlobwithout rendering anything to the screen
Both modes support the same features: headers, footers, watermarks, smart page breaking, full CSS, and more.
Installation
bash
npm install @easypdf/reactBasic Usage
Visual Mode
Attach pdfRef to any element and call downloadPDF to capture it:
tsx
import { useEasyPdf } from "@easypdf/react";
function Report() {
const { pdfRef, downloadPDF, isLoading } = useEasyPdf({
pageSize: "A4",
margins: { top: 20, right: 20, bottom: 20, left: 20 },
footer: {
text: "Page {pageNumber} of {totalPages}",
align: "center",
fontSize: 10,
},
});
return (
<div>
<button
onClick={() => downloadPDF(pdfRef, { filename: "report.pdf" })}
disabled={isLoading}
>
{isLoading ? "Generating..." : "Download PDF"}
</button>
<div
ref={pdfRef}
style={{ padding: "32px", fontFamily: "Arial, sans-serif" }}
>
<h1>Q1 Report</h1>
<p>This element is captured exactly as the browser renders it.</p>
</div>
</div>
);
}Programmatic Mode
Pass JSX directly without rendering it to screen:
tsx
import { useEasyPdf } from "@easypdf/react";
function InvoiceExporter({ invoice }) {
const { createPDF, isLoading } = useEasyPdf();
const handleExport = () =>
createPDF(
<div style={{ padding: "32px", fontFamily: "Arial, sans-serif" }}>
<h1>Invoice #{invoice.id}</h1>
<p>Total: ${invoice.total}</p>
</div>,
{ filename: `invoice-${invoice.id}.pdf` },
);
return (
<button onClick={handleExport} disabled={isLoading}>
{isLoading ? "Generating..." : "Export Invoice"}
</button>
);
}Component Library Support
EasyPdf captures the live DOM — so any CSS the browser renders appears in the PDF. This includes Tailwind CSS, MUI (Material UI), shadcn/ui, Ant Design, styled-components, Emotion, or any other library.
| Library | Status |
|---|---|
| Tailwind CSS | ✅ Full support |
| MUI (Material UI) | ✅ Full support |
| shadcn/ui | ✅ Full support |
| styled-components | ✅ Full support |
| Emotion | ✅ Full support |
| CSS Modules | ✅ Full support |
| Inline styles | ✅ Full support |
SSR / Next.js Support
@easypdf/react is SSR-safe. There are no browser globals at import time. PDF generation is browser-only and guarded internally. Drop it into any Next.js App Router project without extra configuration.
tsx
// app/components/DownloadButton.tsx — must be a client component
"use client";
import { useEasyPdf } from "@easypdf/react";Error Handling
tsx
const { pdfRef, downloadPDF, isLoading, error } = useEasyPdf();
return (
<div>
{error && <p style={{ color: "red" }}>Error: {error.message}</p>}
<button onClick={() => downloadPDF(pdfRef)} disabled={isLoading}>
{isLoading ? "Generating..." : "Download PDF"}
</button>
<div ref={pdfRef}>{/* content */}</div>
</div>
);