Skip to content

feat: render the live preview as the real PDF - #21

Merged
ArcueidMP merged 1 commit into
mainfrom
feat/pdf-live-preview
Sep 15, 2026
Merged

ArcueidMP merged 1 commit into
mainfrom
feat/pdf-live-preview

Conversation

@ArcueidMP

Copy link
Copy Markdown
Owner

Summary

The live preview panel now shows the actual PDF instead of a hand-written HTML approximation of the three templates.

  • The panel renders the current draft through the same browser-side @react-pdf/renderer pipeline as Export PDF, so fonts, colors, spacing, line breaks, and page breaks match the exported file for Classic ATS, Modern ATS, and Chinese Clean.
  • Edits are debounced (300 ms); at most one render runs at a time, input that arrives mid-render is rendered afterwards, and the previous page stays on screen until the next one is ready (status label shows Updating).
  • The PDF is displayed in the browser's built-in viewer from a local blob: object URL with toolbar and nav panes hidden. Preview object URLs are revoked once replaced or when the panel unmounts.
  • createResumePdfBlob now accepts an unvalidated draft so the preview reflects every keystroke; export still validates first.
  • The old HTML preview (ResumePreview.tsx template style tables) is removed.

Security / privacy

  • CSP change: frame-src 'none' becomes frame-src blob: so the same-origin blob PDF can be framed. No other directive changed; no remote source added.
  • The privacy-boundary test now accounts for preview object URLs and asserts that only clicked download URLs reach an anchor and that every created URL is revoked.
  • No console output, no network transport, no storage added. The CJK fonts are still fetched on demand from the same origin, now also when the preview needs them.

Tests

  • New unit tests for the render scheduler (debounce, no overlapping renders, newest input wins, failure recovery, dispose).
  • App tests rewritten around the PDF preview: template switching, keeping the last page while updating, render failure state, object URL hygiene.
  • pnpm format:check, pnpm lint, pnpm typecheck, pnpm test (135 tests), pnpm build all pass locally.
  • Manually verified the production build served with public/_headers applied: all three templates render in the preview under the real CSP, edits update the preview, Chinese Clean loads both bundled fonts, and the console shows no CSP violations.

Trade-offs

  • Browsers without an inline PDF viewer (many mobile browsers) show an empty preview frame; export still works. Documented in README.
  • The PDF renderer chunk now loads on first preview render rather than on first export.
  • The preview is no longer readable by screen readers, since it is a PDF frame rather than DOM text.

Docs

README (new Live Preview section, font loading, CSP note), CHANGELOG (Unreleased: Changed + Security), PRIVACY (preview blob URL boundary, CSP wording).

🤖 Generated with Claude Code

Replace the hand-written HTML approximation of the three templates with a
preview of the actual PDF. The panel renders the current draft through the
same browser-side template pipeline as Export PDF, debounced after edits with
at most one render in flight, keeps the previous page on screen until the next
one is ready, and shows the result in the browser's built-in PDF viewer from a
local blob: object URL that is revoked once replaced.

- Add a small render scheduler (debounce, no overlapping renders, newest
  input wins) and a hook that owns the object URL lifecycle.
- Let createResumePdfBlob accept an unvalidated draft so the preview reflects
  every keystroke; export still validates first.
- Allow same-origin blob: frames in the Cloudflare Pages CSP (frame-src).
- Rewrite the App and privacy-boundary tests around the PDF preview, and add
  unit tests for the scheduler.
- Update README, CHANGELOG, and PRIVACY for the new preview and CSP.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying disposableresume with  Cloudflare Pages  Cloudflare Pages

Latest commit: 21433fe
Status: ✅  Deploy successful!
Preview URL: https://53c21884.disposableresume.pages.dev
Branch Preview URL: https://feat-pdf-live-preview.disposableresume.pages.dev

View logs

@ArcueidMP
ArcueidMP merged commit 8fb5ad1 into main Sep 15, 2026
2 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