Privacy-first visual document builder in the browser. Drag text, images, shapes, and tables on a canvas; export to PDF, DOCX, HTML, or DXP. No account. Editing and storage stay on your device.
- Client-side by default — documents and images live in IndexedDB; nothing is required to leave the browser for normal editing and export.
- Free forever — core editor, templates, exports, and BYOK AI assist are ungated.
- Bring your own key — AI text assist and prompt → document use your provider keys (or local Ollama / LM Studio); keys stay in the browser.
- Canvas editor — multi-page layouts, zoom, multi-select, undo/redo, templates, tables, shapes
- Import / export — PDF (print), DOCX, HTML, DXP package, JSON; basic DOCX import
- AI (BYOK) — improve/write text elements; generate a full canvas document from a prompt; local usage history
- PWA — installable, offline-capable service worker
- Page sizes — A6–A3, B5, Letter, Legal, Executive, Tabloid
make dev # install deps + SvelteKit dev server on :5173
make ci # install → svelte-check → build → link check → tests
make build # production build → apps/web/dist
make preview # preview production buildRequirements: Node 20+, pnpm, Make. Optional: Python 3 (link checker venv via make tools).
SvelteKit 5 · TypeScript · Tailwind CSS · interact.js · JSZip · IndexedDB · Vitest · Playwright · Cloudflare Workers (static assets SPA)
.
├── Makefile # make dev / ci / build / deploy
├── package.json # workspace root + wrangler
├── pnpm-workspace.yaml
├── wrangler.jsonc # Cloudflare assets deploy
├── .github/ # CI, E2E, coverage, Dependabot
├── apps/
│ └── web/ # SvelteKit PWA
└── packages/
└── engine/ # @docxpdf/engine shared document logic
See CONTRIBUTING.md for workflows, tests, and gotchas.
make install # pnpm install in apps/web
make svelte-check # Svelte + TS validation
make test # vitest (web)
make test-engine # vitest (@docxpdf/engine)
make test-e2e # Playwright
make coverage # coverage report
make deploy # build + wrangler deploy
make clean # remove node_modules, dist, cachesOr from the app package:
cd apps/web && pnpm dev
cd apps/web && pnpm build
cd apps/web && pnpm exec vitest runOutput is a static SPA: apps/web/dist (SvelteKit @sveltejs/adapter-static).
These buttons clone this repo into your GitHub account and deploy under your Netlify/Vercel project. You do not need to own or fork prashant-shahi/docxpdf first — sign in, authorize, and deploy.
No env vars required. Config: netlify.toml, vercel.json (install at repo root, build/publish apps/web).
Heroku: not offered. Heroku’s free tier was removed; Eco/Basic are paid. Prefer Netlify, Vercel, Cloudflare, or Docker.
Requires a logged-in Wrangler account:
make build
make deploy # wrangler deploy (Workers static assets)The image is nginx + static files only (no Node toolchain). CI builds the SPA, then pushes to GitHub Container Registry:
docker pull ghcr.io/prashant-shahi/docxpdf:latest
docker run --rm -p 8080:80 ghcr.io/prashant-shahi/docxpdf:latest
# http://localhost:8080Tags:
| Tag | When |
|---|---|
latest |
push to main |
v0.1.0 (etc.) |
git tag v0.1.0 |
pr-<number> |
PR labeled build-image only |
Package: ghcr.io/prashant-shahi/docxpdf.
PR images: add label build-image → CI pushes …:pr-123. Rebuilds on new commits while the label stays. Label removed or PR closed/merged → cleanup deletes that tag (.github/workflows/docker-cleanup.yml).
Local build / run:
make docker-build # make build → docker build
make docker-run # http://localhost:8080Push to GHCR from your machine (gh must be logged in with write:packages):
make docker-login # echo "$(gh auth token)" | docker login ghcr.io -u "$(gh api user -q .login)" --password-stdin
make docker-push # build + push :latestCI uses GITHUB_TOKEN (packages: write). Link the package to this repo and grant Actions Write under package settings → Manage Actions access.
make build
# upload apps/web/dist/ (enable SPA fallback to index.html)