mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-10-03 10:13:47 +10:00
feat(pdf): remove react-pdf and move every consumer to forme
The web preview, downloads, template gallery, server export and public PDF render through Forme. react-pdf, react-pdf-html, the react-pdf hyphenation package, the Phosphor react-pdf icons and the four patches are gone. Hyphenation now follows the page language for every language Forme has patterns for. Semantic CSS keeps its language; declarations Forme can't draw raise an ENGINE_UNSUPPORTED warning in the editor. The page map rebuilds blocks Forme leaves out of its layout when they break across pages, and a render that misplaces a box is repeated with nested rows kept whole. Tests move to a small shim with the react-pdf calls they were written against; tests of react-pdf internals are dropped. Forme limits are recorded as expected failures (RTL line order, characters above U+FFFF).
This commit is contained in:
@@ -51,7 +51,7 @@ flowchart TD
|
||||
| `packages/env` | Server environment validation and root `.env` loading |
|
||||
| `packages/schema` | Zod schemas and typed resume/page/template models |
|
||||
| `packages/resume` | Pure resume-domain helpers, including JSON Patch behavior and network icon mapping |
|
||||
| `packages/pdf` | React PDF document, template primitives, templates, font registration, and browser/server generation adapters |
|
||||
| `packages/pdf` | Resume document, template primitives, Forme conversion, templates, font registration, and browser/server generation adapters |
|
||||
| `packages/docx` | DOCX export generation |
|
||||
| `packages/mcp` | MCP tools, prompts, resources, server card, and tool metadata |
|
||||
| `packages/ui` | Shared Base UI/shadcn-style primitives and hooks |
|
||||
@@ -93,7 +93,7 @@ When adding code, choose the owner by behavior:
|
||||
| API procedure or authenticated business behavior | `packages/api/src/features/<domain>` |
|
||||
| Pure resume data logic | `packages/resume` |
|
||||
| Resume schema or template list shape | `packages/schema` |
|
||||
| React PDF template/rendering behavior | `packages/pdf` |
|
||||
| PDF template/rendering behavior | `packages/pdf` |
|
||||
| PDF.js canvas/viewer UI | `apps/web/src/features/resume` |
|
||||
| DOCX export behavior | `packages/docx` |
|
||||
| MCP tool/prompt/resource behavior | `packages/mcp` |
|
||||
@@ -124,7 +124,7 @@ Avoid reintroducing technical-layer folders such as `services/` or `helpers/` at
|
||||
|
||||
## PDF and export boundaries
|
||||
|
||||
`packages/pdf` owns React PDF generation:
|
||||
`packages/pdf` owns PDF generation. Templates are written with React primitives; `src/forme` renders them with a small React renderer and converts the result into a [Forme](https://www.formepdf.com/) document, which the Forme engine (WebAssembly) lays out and draws:
|
||||
|
||||
- `@reactive-resume/pdf/browser` creates browser PDF blobs.
|
||||
- `@reactive-resume/pdf/server` creates server PDF files.
|
||||
|
||||
@@ -43,7 +43,7 @@ These steps set up Reactive Resume for local development, whether you're contrib
|
||||
- **SeaweedFS** — S3-compatible storage (port 8333)
|
||||
|
||||
<Info>
|
||||
**From v5.1.0 onwards** — PDF generation now runs entirely in the browser via `@react-pdf/renderer`, so no Browserless or Chromium container is required for development.
|
||||
**From v5.1.0 onwards** — PDF generation now runs entirely in the browser with the Forme PDF engine (WebAssembly), so no Browserless or Chromium container is required for development.
|
||||
</Info>
|
||||
|
||||
<Tip>
|
||||
@@ -164,7 +164,7 @@ reactive-resume/
|
||||
│ ├── db/ # Drizzle client and schema
|
||||
│ ├── docx/ # DOCX export generation
|
||||
│ ├── mcp/ # MCP tools, prompts, resources, and metadata
|
||||
│ ├── pdf/ # React PDF rendering and PDF generation adapters
|
||||
│ ├── pdf/ # PDF rendering (Forme) and PDF generation adapters
|
||||
│ ├── resume/ # Pure resume-domain helpers
|
||||
│ ├── schema/ # Zod schemas and typed models
|
||||
│ ├── ui/ # Shared Base UI/shadcn-style primitives
|
||||
|
||||
@@ -52,7 +52,7 @@ The easiest way to use Reactive Resume is our cloud version at [rxresu.me](https
|
||||
You can deploy Reactive Resume on your own infrastructure using Docker.
|
||||
|
||||
<Info>
|
||||
**From v5.1.0 onwards** — PDF generation now runs entirely client-side via `@react-pdf/renderer`. Self-hosted deployments no longer require Browserless, Chromium, or any external print service as a dependency. The `PRINTER_*` and `BROWSERLESS_*` environment variables are no longer read and can be removed from your `.env`.
|
||||
**From v5.1.0 onwards** — PDF generation now runs entirely client-side with the Forme PDF engine (WebAssembly). Self-hosted deployments no longer require Browserless, Chromium, or any external print service as a dependency. The `PRINTER_*` and `BROWSERLESS_*` environment variables are no longer read and can be removed from your `.env`.
|
||||
</Info>
|
||||
|
||||
### Prerequisites
|
||||
|
||||
@@ -4714,7 +4714,7 @@ The full JSON Schema for Reactive Resume follows. You can also fetch the latest
|
||||
"description": "Personal notes for the resume. Can be used to add any additional information or instructions for the resume. These notes are not displayed on the resume, they are only visible to the author of the resume when editing the resume. This should be a HTML-formatted string."
|
||||
},
|
||||
"styleRules": {
|
||||
"description": "Structured style rules that target semantic resume sections and slots for React PDF rendering.",
|
||||
"description": "Structured style rules that target semantic resume sections and slots for PDF rendering.",
|
||||
"type": "array",
|
||||
"items": {}
|
||||
},
|
||||
|
||||
@@ -131,7 +131,7 @@ We share information only as needed to provide the Service:
|
||||
|
||||
### PDF generation (client-side)
|
||||
|
||||
When you export to PDF, the Service renders the document directly in your browser using `@react-pdf/renderer`. Resume content is processed locally on your device for this purpose and is not sent to a separate rendering service. No third-party "printer" or headless-browser service is involved in the export.
|
||||
When you export to PDF, the Service renders the document directly in your browser using the Forme PDF engine, which runs in your browser as WebAssembly. Resume content is processed locally on your device for this purpose and is not sent to a separate rendering service. No third-party "printer" or headless-browser service is involved in the export.
|
||||
|
||||
### Storage providers (optional)
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ You represent that you have the rights necessary to upload and use any files and
|
||||
|
||||
## Exports (PDF)
|
||||
|
||||
When you request a PDF export, the Service renders the document in your own browser using `@react-pdf/renderer`. Your resume content is processed locally by the JavaScript running on your device; it is not transmitted to a separate rendering service for the purpose of generating the PDF.
|
||||
When you request a PDF export, the Service renders the document in your own browser using the Forme PDF engine. Your resume content is processed locally by the JavaScript running on your device; it is not transmitted to a separate rendering service for the purpose of generating the PDF.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ description: "How to self-host Reactive Resume with Docker (Postgres only), with
|
||||
---
|
||||
|
||||
<Info>
|
||||
**From v5.1.0 onwards** — PDF generation now runs entirely client-side via `@react-pdf/renderer`. New deployments no longer require Browserless, Chromium, or any external print service as a dependency. The `PRINTER_*` and `BROWSERLESS_*` environment variables are no longer read and can be removed from your `.env`.
|
||||
**From v5.1.0 onwards** — PDF generation now runs entirely client-side with the Forme PDF engine (WebAssembly). New deployments no longer require Browserless, Chromium, or any external print service as a dependency. The `PRINTER_*` and `BROWSERLESS_*` environment variables are no longer read and can be removed from your `.env`.
|
||||
</Info>
|
||||
|
||||
## Overview
|
||||
@@ -541,8 +541,8 @@ A healthy response returns HTTP 200. If you get a different status code, the JSO
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="PDF export fails or downloads an empty file">
|
||||
- **Common cause**: PDFs are now rendered in the browser via `@react-pdf/renderer`, so failures usually come from a
|
||||
blocked download, an extreme browser memory limit, or a custom CSP that strips inline workers. - **Checks**: confirm
|
||||
- **Common cause**: PDFs are now rendered in the browser with the Forme PDF engine (WebAssembly), so failures usually come from a
|
||||
blocked download, an extreme browser memory limit, or a custom CSP that blocks WebAssembly (it needs `'wasm-unsafe-eval'` in `script-src`). - **Checks**: confirm
|
||||
the browser is up to date, the page hasn't been opened in a restricted iframe, and that no extension is intercepting
|
||||
the download. There is no server-side printer to inspect.
|
||||
</Accordion>
|
||||
|
||||
@@ -4,7 +4,7 @@ description: "Ready-to-use Docker Compose examples for self-hosting Reactive Res
|
||||
---
|
||||
|
||||
<Info>
|
||||
**From v5.1.0 onwards** — PDF generation now runs entirely client-side via `@react-pdf/renderer`. None of the examples below require a Browserless or Chromium service. Older configurations that still define a `printer` service or set `BROWSERLESS_TOKEN` / `PRINTER_*` will continue to start, but those services are inert and can be removed.
|
||||
**From v5.1.0 onwards** — PDF generation now runs entirely client-side with the Forme PDF engine (WebAssembly). None of the examples below require a Browserless or Chromium service. Older configurations that still define a `printer` service or set `BROWSERLESS_TOKEN` / `PRINTER_*` will continue to start, but those services are inert and can be removed.
|
||||
</Info>
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -4,7 +4,7 @@ description: "How to self-host Reactive Resume on Kubernetes with plain manifest
|
||||
---
|
||||
|
||||
<Info>
|
||||
**From v5.1.0 onwards** — the builder generates PDFs in the browser via `@react-pdf/renderer`. New deployments no
|
||||
**From v5.1.0 onwards** — the builder generates PDFs in the browser with the Forme PDF engine (WebAssembly). New deployments no
|
||||
longer require Browserless, Chromium, or any external print service as a dependency. The `PRINTER_*` and
|
||||
`BROWSERLESS_*` environment variables are no longer read and can be removed from your configuration.
|
||||
</Info>
|
||||
@@ -416,8 +416,8 @@ curl -f http://localhost:3000/api/health
|
||||
</Step>
|
||||
|
||||
<Step title="Export a PDF">
|
||||
Open **Download** in the builder header and choose **PDF**. Builder PDF rendering happens in the browser via
|
||||
`@react-pdf/renderer`. Open the downloaded file and check its text, fonts, and picture.
|
||||
Open **Download** in the builder header and choose **PDF**. Builder PDF rendering happens in the browser with
|
||||
the Forme PDF engine. Open the downloaded file and check its text, fonts, and picture.
|
||||
</Step>
|
||||
|
||||
<Step title="Check persistence">
|
||||
|
||||
+20
-20
@@ -9800,7 +9800,7 @@
|
||||
"get": {
|
||||
"operationId": "exportAccountData",
|
||||
"summary": "Export user account data",
|
||||
"description": "Returns a JSON-serializable export of the authenticated user's data, including their public profile fields, resumes, and independent cover letters. Images remain URL references. Secrets such as password hashes, tokens, and API keys are never included. Requires authentication.",
|
||||
"description": "Returns a JSON-serializable export of the authenticated user's data, including their public profile fields, resumes, independent cover letters and job applications. Images remain URL references. Secrets such as password hashes, tokens, and API keys are never included. Requires authentication.",
|
||||
"tags": [
|
||||
"Authentication"
|
||||
],
|
||||
@@ -10365,7 +10365,7 @@
|
||||
"description": "The typography settings of the resume. Determines the fonts and sizes of the body and headings of the resume."
|
||||
},
|
||||
"styleRules": {
|
||||
"description": "Structured style rules that target semantic resume sections and slots for React PDF rendering."
|
||||
"description": "Structured style rules that target semantic resume sections and slots for PDF rendering."
|
||||
},
|
||||
"stylesheet": {
|
||||
"type": "object",
|
||||
@@ -11108,7 +11108,7 @@
|
||||
"description": "The typography settings of the resume. Determines the fonts and sizes of the body and headings of the resume."
|
||||
},
|
||||
"styleRules": {
|
||||
"description": "Structured style rules that target semantic resume sections and slots for React PDF rendering."
|
||||
"description": "Structured style rules that target semantic resume sections and slots for PDF rendering."
|
||||
},
|
||||
"stylesheet": {
|
||||
"type": "object",
|
||||
@@ -11766,7 +11766,7 @@
|
||||
"description": "The typography settings of the resume. Determines the fonts and sizes of the body and headings of the resume."
|
||||
},
|
||||
"styleRules": {
|
||||
"description": "Structured style rules that target semantic resume sections and slots for React PDF rendering."
|
||||
"description": "Structured style rules that target semantic resume sections and slots for PDF rendering."
|
||||
},
|
||||
"stylesheet": {
|
||||
"type": "object",
|
||||
@@ -12533,7 +12533,7 @@
|
||||
"description": "The typography settings of the resume. Determines the fonts and sizes of the body and headings of the resume."
|
||||
},
|
||||
"styleRules": {
|
||||
"description": "Structured style rules that target semantic resume sections and slots for React PDF rendering."
|
||||
"description": "Structured style rules that target semantic resume sections and slots for PDF rendering."
|
||||
},
|
||||
"stylesheet": {
|
||||
"type": "object",
|
||||
@@ -13274,7 +13274,7 @@
|
||||
"description": "The typography settings of the resume. Determines the fonts and sizes of the body and headings of the resume."
|
||||
},
|
||||
"styleRules": {
|
||||
"description": "Structured style rules that target semantic resume sections and slots for React PDF rendering."
|
||||
"description": "Structured style rules that target semantic resume sections and slots for PDF rendering."
|
||||
},
|
||||
"stylesheet": {
|
||||
"type": "object",
|
||||
@@ -13949,7 +13949,7 @@
|
||||
"description": "The typography settings of the resume. Determines the fonts and sizes of the body and headings of the resume."
|
||||
},
|
||||
"styleRules": {
|
||||
"description": "Structured style rules that target semantic resume sections and slots for React PDF rendering."
|
||||
"description": "Structured style rules that target semantic resume sections and slots for PDF rendering."
|
||||
},
|
||||
"stylesheet": {
|
||||
"type": "object",
|
||||
@@ -14630,7 +14630,7 @@
|
||||
"description": "The typography settings of the resume. Determines the fonts and sizes of the body and headings of the resume."
|
||||
},
|
||||
"styleRules": {
|
||||
"description": "Structured style rules that target semantic resume sections and slots for React PDF rendering."
|
||||
"description": "Structured style rules that target semantic resume sections and slots for PDF rendering."
|
||||
},
|
||||
"stylesheet": {
|
||||
"type": "object",
|
||||
@@ -15288,7 +15288,7 @@
|
||||
"description": "The typography settings of the resume. Determines the fonts and sizes of the body and headings of the resume."
|
||||
},
|
||||
"styleRules": {
|
||||
"description": "Structured style rules that target semantic resume sections and slots for React PDF rendering."
|
||||
"description": "Structured style rules that target semantic resume sections and slots for PDF rendering."
|
||||
},
|
||||
"stylesheet": {
|
||||
"type": "object",
|
||||
@@ -15888,7 +15888,7 @@
|
||||
"styleRules": {
|
||||
"type": "array",
|
||||
"items": {},
|
||||
"description": "Structured style rules that target semantic resume sections and slots for React PDF rendering."
|
||||
"description": "Structured style rules that target semantic resume sections and slots for PDF rendering."
|
||||
},
|
||||
"stylesheet": {
|
||||
"type": "object",
|
||||
@@ -16479,7 +16479,7 @@
|
||||
"description": "The typography settings of the resume. Determines the fonts and sizes of the body and headings of the resume."
|
||||
},
|
||||
"styleRules": {
|
||||
"description": "Structured style rules that target semantic resume sections and slots for React PDF rendering."
|
||||
"description": "Structured style rules that target semantic resume sections and slots for PDF rendering."
|
||||
},
|
||||
"stylesheet": {
|
||||
"type": "object",
|
||||
@@ -17341,7 +17341,7 @@
|
||||
"description": "The typography settings of the resume. Determines the fonts and sizes of the body and headings of the resume."
|
||||
},
|
||||
"styleRules": {
|
||||
"description": "Structured style rules that target semantic resume sections and slots for React PDF rendering."
|
||||
"description": "Structured style rules that target semantic resume sections and slots for PDF rendering."
|
||||
},
|
||||
"stylesheet": {
|
||||
"type": "object",
|
||||
@@ -18099,7 +18099,7 @@
|
||||
"description": "The typography settings of the resume. Determines the fonts and sizes of the body and headings of the resume."
|
||||
},
|
||||
"styleRules": {
|
||||
"description": "Structured style rules that target semantic resume sections and slots for React PDF rendering."
|
||||
"description": "Structured style rules that target semantic resume sections and slots for PDF rendering."
|
||||
},
|
||||
"stylesheet": {
|
||||
"type": "object",
|
||||
@@ -23809,7 +23809,7 @@
|
||||
"description": "Personal notes for the resume. Can be used to add any additional information or instructions for the resume. These notes are not displayed on the resume, they are only visible to the author of the resume when editing the resume. This should be a HTML-formatted string."
|
||||
},
|
||||
"styleRules": {
|
||||
"description": "Structured style rules that target semantic resume sections and slots for React PDF rendering."
|
||||
"description": "Structured style rules that target semantic resume sections and slots for PDF rendering."
|
||||
},
|
||||
"stylesheet": {
|
||||
"type": "object",
|
||||
@@ -28168,7 +28168,7 @@
|
||||
"description": "Personal notes for the resume. Can be used to add any additional information or instructions for the resume. These notes are not displayed on the resume, they are only visible to the author of the resume when editing the resume. This should be a HTML-formatted string."
|
||||
},
|
||||
"styleRules": {
|
||||
"description": "Structured style rules that target semantic resume sections and slots for React PDF rendering."
|
||||
"description": "Structured style rules that target semantic resume sections and slots for PDF rendering."
|
||||
},
|
||||
"stylesheet": {
|
||||
"type": "object",
|
||||
@@ -32662,7 +32662,7 @@
|
||||
"description": "Personal notes for the resume. Can be used to add any additional information or instructions for the resume. These notes are not displayed on the resume, they are only visible to the author of the resume when editing the resume. This should be a HTML-formatted string."
|
||||
},
|
||||
"styleRules": {
|
||||
"description": "Structured style rules that target semantic resume sections and slots for React PDF rendering."
|
||||
"description": "Structured style rules that target semantic resume sections and slots for PDF rendering."
|
||||
},
|
||||
"stylesheet": {
|
||||
"type": "object",
|
||||
@@ -37127,7 +37127,7 @@
|
||||
"description": "Personal notes for the resume. Can be used to add any additional information or instructions for the resume. These notes are not displayed on the resume, they are only visible to the author of the resume when editing the resume. This should be a HTML-formatted string."
|
||||
},
|
||||
"styleRules": {
|
||||
"description": "Structured style rules that target semantic resume sections and slots for React PDF rendering."
|
||||
"description": "Structured style rules that target semantic resume sections and slots for PDF rendering."
|
||||
},
|
||||
"stylesheet": {
|
||||
"type": "object",
|
||||
@@ -42080,7 +42080,7 @@
|
||||
"description": "Personal notes for the resume. Can be used to add any additional information or instructions for the resume. These notes are not displayed on the resume, they are only visible to the author of the resume when editing the resume. This should be a HTML-formatted string."
|
||||
},
|
||||
"styleRules": {
|
||||
"description": "Structured style rules that target semantic resume sections and slots for React PDF rendering."
|
||||
"description": "Structured style rules that target semantic resume sections and slots for PDF rendering."
|
||||
},
|
||||
"stylesheet": {
|
||||
"type": "object",
|
||||
@@ -46537,7 +46537,7 @@
|
||||
"description": "Personal notes for the resume. Can be used to add any additional information or instructions for the resume. These notes are not displayed on the resume, they are only visible to the author of the resume when editing the resume. This should be a HTML-formatted string."
|
||||
},
|
||||
"styleRules": {
|
||||
"description": "Structured style rules that target semantic resume sections and slots for React PDF rendering."
|
||||
"description": "Structured style rules that target semantic resume sections and slots for PDF rendering."
|
||||
},
|
||||
"stylesheet": {
|
||||
"type": "object",
|
||||
@@ -51353,7 +51353,7 @@
|
||||
"description": "Personal notes for the resume. Can be used to add any additional information or instructions for the resume. These notes are not displayed on the resume, they are only visible to the author of the resume when editing the resume. This should be a HTML-formatted string."
|
||||
},
|
||||
"styleRules": {
|
||||
"description": "Structured style rules that target semantic resume sections and slots for React PDF rendering.",
|
||||
"description": "Structured style rules that target semantic resume sections and slots for PDF rendering.",
|
||||
"type": "array",
|
||||
"items": {}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user