The one-line difference
@react-pdf/renderer is a React reconciler that turns JSX into PDFs at runtime in your browser or Node bundle. makesPDF is a hosted REST API: you POST markdown or a compact DSL string and get back a PDF that's PDF/A-2A archival + PDF/UA-1 accessible by construction. No React in your build, no Yoga in your bundle, no fonts to ship, no CI worry about whether the output is compliant.
Feature matrix
| react-pdf | makesPDF | |
|---|---|---|
| Shape | React library (npm) | Hosted REST API (/api/v1/*) |
| Authoring surface | JSX (<Document><Page><View>) |
Markdown, builder DSL, JSON |
| Runtime | Your browser or Node process | Cloudflare Workers (we host) |
| Bundle cost | ~600 KB minified (Yoga + PDFKit + Fontkit) | 0 KB — you call an HTTP endpoint |
| Tagged PDF (PDF/UA-1) | No | Yes, by default |
| PDF/A-2A archival | No | Yes, by default |
| veraPDF-validated output | No | Yes |
| Built-in markdown input | No | Yes (POST /api/v1/md) |
| AI / agent first-class | No | Yes — public skill file, MCP server, x402-payable |
| CLI | Community | First-party (@makespdf/cli) |
| License | MIT (community OSS) | Proprietary hosted; skill file MIT |
Same input, two outputs
A "Hello, Ada" document.
react-pdf — JSX in your bundle:
import { Document, Page, View, Text, StyleSheet, pdf } from "@react-pdf/renderer";
const styles = StyleSheet.create({
page: { padding: 40, fontSize: 12 },
heading: { fontSize: 24, marginBottom: 12 },
});
const Doc = () => (
<Document>
<Page size="A4" style={styles.page}>
<View>
<Text style={styles.heading}>Hello, Ada</Text>
<Text>Welcome to the report.</Text>
</View>
</Page>
</Document>
);
const blob = await pdf(<Doc />).toBlob();
makesPDF — one HTTP call, no React:
curl -X POST https://makespdf.com/api/v1/md \
-H "Authorization: Bearer $MAKESPDF_API_KEY" \
-H "Content-Type: application/json" \
-d '{"markdown": "# Hello, Ada\n\nWelcome to the report."}' \
-o hello.pdf
Or with the builder DSL when you want full control:
curl -X POST https://makespdf.com/api/v1/preview \
-H "Authorization: Bearer $MAKESPDF_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"dsl": "const template = doc({ size: \"A4\" }, page({ padding: 40 }, h1(\"Hello, {{name}}\"), p(\"Welcome to the report.\")));\nconst sampleData = { name: \"Ada\" };",
"data": { "name": "Ada" }
}' -o hello.pdf
The output PDF is a tagged document with proper H1 / P structure elements — open it in Acrobat's Tags pane and you'll see real semantic structure, not anonymous BT/ET text runs. react-pdf's output is untagged: screen readers see one continuous run of text per page.
Why people switch
- Compliance is a deadline, not a feature. ADA Title II tier 1 (US public entities ≥50k) hits April 26, 2026. The European Accessibility Act started June 28, 2025. PDF/UA-1 isn't a "would be nice" — it's a procurement and audit requirement. react-pdf doesn't emit a structure tree; you can't bolt PDF/UA on after the fact without a separate remediation tool. makesPDF tags by construction and validates against veraPDF (the ISO reference validator).
- The bundle hurts. PDFKit + Fontkit + Yoga together push 600KB+ of JS into apps that just want to generate a receipt. Hosted means zero bytes shipped.
- Determinism. Same input → same bytes. react-pdf depends on Yoga's flexbox engine and PDFKit's text wrapper, both of which can shift layout between versions. makesPDF's renderer is a single owned pipeline; output is byte-stable.
- Markdown is faster than JSX for content. Most real documents are mostly content — the JSX tax shows up the moment you have to render a 30-line invoice description or paste in a Markdown blog post.
- Agents need an API, not a library. If you're orchestrating an LLM that generates documents, JSX-in-Node is a chore. A hosted endpoint with a skill file (
/skills/pdf-template-author.md) is the agent-native path.
When react-pdf is still the right call
- You need to render PDFs inside the user's browser (e.g. an offline-capable app) and round-tripping through a hosted API isn't acceptable.
- You're already shipping React server-side and a single in-process render is cheaper than an HTTP hop.
- You want a community OSS license you can fork and audit end-to-end.
For most server-side or agent-driven workloads, the hosted endpoint wins on bundle size, compliance, and operational surface area.
Migration
A /ai/migrate converter that takes pasted react-pdf JSX and emits builder-DSL is on the roadmap. For now, see the skill file for the DSL function reference; most react-pdf documents map cleanly to doc(page(col(...))) with font-*, padding, and margin styles that look almost identical.
For the deeper architectural comparison — the 16-step layout pipeline, font subsetting, and structure tree generation — see our API docs.