Skip to content

fix(pdf): generate the PDF in-browser — identical on every device - #2

Merged
pythonsst merged 1 commit into
mainfrom
fix/pdf-client-render
Jun 27, 2026
Merged

fix(pdf): generate the PDF in-browser — identical on every device#2
pythonsst merged 1 commit into
mainfrom
fix/pdf-client-render

Conversation

@pythonsst

Copy link
Copy Markdown
Owner

Why

We kept patching individual browser print-engine quirks (iOS WebKit ignores @page { margin: 0 } and inserts blank sheets; desktop Chrome needs Background graphics on; the iOS height-budget made desktop pages look half-empty). Desktop and iOS want opposite things, so window.print() can't satisfy both.

What

Render the PDF ourselves in the browser: capture each already-laid-out .a4 page to an image (html2canvas-pro) and place one per A4 sheet in a jsPDF. The output is byte-identical on desktop Chrome, iPhone Safari/Chrome and Android — full-page frames and backgrounds always included — and the biodata still never leaves the browser (libs are lazy-loaded on click).

Key detail

The preview scales the document down with a CSS transform (heavily on mobile). Capturing under that transform squished the layout, so onclone resets the transform → every device captures at true A4 size.

Changes

  • src/lib/pdf.tsdownloadBiodataPdf(); + unit tests (mocked libs).
  • create page — Download PDF calls the generator with a "Preparing…" state; file named from the person's name.
  • Revert iOS print workarounds (page-height budget in FramedDoc, print min-height override) now that the print engine is out of the loop — pages are full A4 again on screen and in the PDF.

Verification

  • npm run lint clean · npm test 37/37 · next build green.
  • Headless downloads in desktop + mobile emulation produced byte-identical 2-page PDFs (Traditional + Floral), full frames intact. (Screenshots of the rendered PDFs reviewed locally.)

🤖 Generated with Claude Code

…evice

Stop using window.print(): each browser's print engine paginates differently
(iOS WebKit ignores @page margin:0 and inserts blank sheets; desktop Chrome
needs "Background graphics" enabled; pages looked half-empty after the iOS
workarounds). That whack-a-mole can't satisfy desktop and iOS at once.

Instead we render each laid-out A4 page to an image (html2canvas-pro) and place
one per A4 sheet in a jsPDF. Output is identical on desktop Chrome, iPhone
Safari/Chrome and Android, full-page frames and backgrounds always included,
and the biodata still never leaves the browser (libs are lazy-loaded on click).

- src/lib/pdf.ts: downloadBiodataPdf() — captures #print-area's .a4 pages.
  onclone resets the preview's CSS scale transform so capture is at true A4
  size on every device (mobile previously squished).
- create page: Download PDF now calls the generator (with a "Preparing…"
  state) and names the file from the person's name.
- Revert the iOS-specific print workarounds (page-height budget, print
  min-height override) now that we don't depend on the print engine — pages
  are full A4 again on screen and in the PDF.
- Tests: mocked unit tests for the page-iteration logic (37 total).

Verified: headless downloads on desktop + mobile emulation produce byte-
identical 2-page PDFs (traditional + floral), full frames intact.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
snapbiodata Ready Ready Preview, Comment Jun 27, 2026 9:57pm

@pythonsst
pythonsst merged commit 12e863a into main Jun 27, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant