* fix(pdf): align textkit line-box and font metrics to browser behaviour CJK characters in resumes with a tightened typography line-height (< ~1.4) had their descenders clipped by the next line. Latin glyphs in the same resume rendered fine. Fixes the visual regression vs the v5.0.x Puppeteer-based renderer reported in issue #2986 and follow-ups. The clipping is caused by two independent gaps in @react-pdf/textkit relative to standard CSS line-box rules: 1. `height(run)` short-circuits to the user-supplied lineHeight and ignores the run's intrinsic ascent + descent. CSS line-boxes are spec'd as `max(line-height, content-area)` — when CJK glyphs are present the content-area is taller than a tightened lineHeight, so the box must grow. textkit didn't, so the baseline (computed from the real, larger CJK ascent) sat below the box and the descender bled into the next line. 2. `ascent / descent / lineGap` are read directly from fontkit's hhea defaults. For Source Han Sans/Serif (the CJK fallbacks registered in #3013) hhea is intentionally inflated for legacy Windows GDI compatibility (1.45 em vs 1.0 em), so even a fixed line-box would have been excessively tall. Browsers (and the v5.0.x Puppeteer renderer) read OS/2 sTypoAscender/Descender/LineGap instead, which are the values the type designers intend for modern shaping. Both are upstream behaviours of `@react-pdf/textkit`, but waiting for an upstream release would leave existing users with broken CJK output. The fix is shipped as a pnpm patch (~30 LOC): - `resolveTypoMetrics(font)`: prefer OS/2 typo metrics, fall back to hhea when an OS/2 table is absent (e.g. the StandardFont stand-ins for Helvetica/Courier/Times). Used by ascent/descent/lineGap so all height-related calculations stay consistent. - `height(run)`: `Math.max(lineHeight || 0, intrinsic)` instead of the original short-circuit, matching CSS line-box rules. The patch is self-contained: existing Latin-only resumes are unaffected (IBM Plex Serif's typo metrics equal hhea; Roboto's typo is slightly smaller, but only changes the rendered line-box for users who set lineHeight below ~1.17, which already used to clip ascenders under v5.1.x and now lays out as it would in a browser). Tooling notes: - `Dockerfile.dev` copies `patches/` before `pnpm install` so the dev image build no longer fails on `--frozen-lockfile`. The production `Dockerfile` already gets it for free via `turbo prune --docker` (the patch reference in package.json marks the directory as part of the pruned slice). - The patch will become a no-op once an equivalent fix lands upstream in @react-pdf/textkit; the entry can then be removed from `pnpm.patchedDependencies` and the file deleted. * fix(deps): regenerate lockfile and move patchedDependencies for pnpm 11 The previous commit's lockfile was authored by pnpm 8 (lockfileVersion 6.0) and kept patchedDependencies under package.json#pnpm. The repository now declares packageManager: pnpm@11.1.2, which: - writes lockfileVersion 9.0 and rejects v6 with ERR_PNPM_LOCKFILE_BREAKING_CHANGE on --frozen-lockfile (CI failure observed in autofix.ci); - reads pnpm settings from pnpm-workspace.yaml, silently ignoring the package.json#pnpm field — so the textkit patch was no longer applied. Regenerate pnpm-lock.yaml with pnpm 11.1.2 and move patchedDependencies to pnpm-workspace.yaml so the patch is applied and CI passes. * chore: update dependencies --------- Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
Reactive Resume
Reactive Resume is a free and open-source resume builder that simplifies the process of creating, updating, and sharing your resume.
Reactive Resume makes building resumes straightforward. Pick a template, fill in your details, and export to PDF—no account required for basic use. For those who want more control, the entire application can be self-hosted on your own infrastructure.
Built with privacy as a core principle, Reactive Resume gives you complete ownership of your data. The codebase is fully open-source under the MIT license, with no tracking, no ads, and no hidden costs.
Features
Resume Building
- Real-time preview as you type
- Multiple export formats (PDF, JSON, DOCX)
- Drag-and-drop section ordering
- Custom sections for any content type
- Rich text editor with formatting support
Templates
- Professionally designed templates
- A4 and Letter size support
- Customizable colors, fonts, and spacing
- Custom CSS for advanced styling
Privacy & Control
- Self-host on your own infrastructure
- No tracking or analytics by default
- Full data export at any time
- Delete your data permanently with one click
Extras
- AI integration (OpenAI, Google Gemini, Anthropic Claude)
- Multi-language support
- Share resumes via unique links
- Import from JSON Resume format
- Dark mode support
- Passkey and two-factor authentication
Templates
Azurill |
Bronzor |
Chikorita |
Ditto |
Gengar |
Glalie |
Kakuna |
Lapras |
Leafish |
Onyx |
Pikachu |
Rhyhorn |
Ditgar |
Meowth |
Scizor |
Quick Start
The quickest way to run Reactive Resume locally:
# Clone the repository
git clone https://github.com/amruthpillai/reactive-resume.git
cd reactive-resume
# Start all services
docker compose up -d
# Access the app
open http://localhost:3000
For detailed setup instructions, environment configuration, and self-hosting guides, see the documentation.
Tech Stack
| Category | Technology |
|---|---|
| Framework | TanStack Start (React 19, Vite) |
| Runtime | Node.js |
| Language | TypeScript |
| Database | PostgreSQL with Drizzle ORM |
| API | ORPC (Type-safe RPC) |
| Auth | Better Auth |
| Styling | Tailwind CSS |
| UI Components | Radix UI |
| State Management | Zustand + TanStack Query |
Documentation
Comprehensive guides are available at docs.rxresu.me:
| Guide | Description |
|---|---|
| Getting Started | First-time setup and basic usage |
| Self-Hosting | Deploy on your own server |
| Development Setup | Local development environment |
| Project Architecture | Codebase structure and patterns |
| Exporting Your Resume | PDF and JSON export options |
Self-Hosting
Reactive Resume can be self-hosted using Docker. The stack includes:
- PostgreSQL — Database for storing user data and resumes
- SeaweedFS (optional) — S3-compatible storage for file uploads
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. ThePRINTER_*andBROWSERLESS_*environment variables are no longer read and can be removed from your.env.
Pull the latest image from Docker Hub or GitHub Container Registry:
# Docker Hub
docker pull amruthpillai/reactive-resume:latest
# GitHub Container Registry
docker pull ghcr.io/amruthpillai/reactive-resume:latest
See the self-hosting guide for complete instructions.
Support
Reactive Resume is and always will be free and open-source. If it has helped you land a job or saved you time, please consider supporting continued development:
Other ways to support:
- Star this repository
- Report bugs and suggest features
- Improve documentation
- Help with translations
Star History
Contributing
Contributions make open-source thrive. Whether fixing a typo or adding a feature, all contributions are welcome.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
See the development setup guide for detailed instructions on how to set up the project locally.
License
MIT — do whatever you want with it.














