Free, open-source, 100% client-side PDF signer + form filler (in-person, hand-the-device flow).
- Vite + React + TypeScript
pdfjs-distfor renderingpdf-libfor flattening export- IndexedDB (
idb-keyval) for local caching - PWA via
vite-plugin-pwa - Vitest + Playwright + pixelmatch
- A) Base PDF bytes: immutable
Uint8Array - B) Overlay Model:
DocPackageV1JSON document (src/model/types.ts,src/model/schema/freesign.v1.schema.json) - C) View/UI State: zoom/tool/selection/mode/signer/snap
- Pipeline: render with pdf.js canvas + DOM overlay, then flatten values back into original PDF using pdf-lib.
pnpm install
pnpm devpnpm buildpnpm test
pnpm e2e- Upload PDF.
- Choose Signature/Text/Date/Initials/Checkbox tool.
- Place fields and fill them (double click field to fill).
- Export PDF.
- Upload PDF.
- Keep app in Prepare mode and place fields for signer 1/2.
- Switch to Signing mode.
- Select
Hand to Signer 1orHand to Signer 2. - Only active signer fields are editable/focused.
- Install/open once while online.
- After service worker is ready, app shows Offline ready.
- App can reopen and use cached assets offline.
- PDF export fidelity — exported PDF field positions may not match on-screen placement exactly. Actively being fixed.
- MVP text fields are single-line shrink-to-fit (clip at min size).
- Export font is Helvetica; non-Latin scripts may require custom font embedding in future (
fontkithook not yet included). - Current MVP uses one-page-oriented UI behavior even though document model is page-capable.
- Field placement and resize handles still being refined.
- Run
pnpm test - Run
pnpm e2e - Open app offline after first load
- Export PDF visually matches overlay placement