Free PDF tools that run entirely in your browser. Merge, split, compress, edit, watermark/stamp, check-or-remove signatures, check what a file reveals (and strip it), and password-protect/unlock PDFs — no file is ever uploaded to a server. localdobe.com is a static site; every tool executes client-side and works offline once you've visited it.
SEO-STRATEGY.md— keyword/GEO strategy, page→keyword mapping, intent traps, and the technical SEO foundation (trailing-slash canonicals, sitemap, schema).DEPLOY.md— deployment via Cloudflare Workers Builds (push tomain).SELF-HOSTING.md— run your own copy on any static host (build steps, nginx/Caddy configs, cache headers, what to change so it stops pointing at localdobe.com).
| Tool | Page | What it does |
|---|---|---|
| Merge | /merge-pdf |
Combine multiple PDFs into one, reorder pages first |
| Split | /split-pdf |
Extract page ranges into separate PDFs, zipped client-side |
| Compress | /compress-pdf |
Shrink file size via pdfcpu (Light / Balanced / Maximum lossless presets, plus a lossy Shrink images preset that downsamples scans to 150 dpi) |
| Edit | /edit-pdf |
Click-to-edit text in place, rotate, delete/insert and resize pages |
| Watermark & Stamp | /watermark-pdf |
Add a text/image watermark or stamp; remove existing ones |
| Signatures | /validate-pdf-signature |
Validate digital signatures, inspect evidence, or remove them |
| Privacy Check | /pdf-privacy-check |
See what a PDF reveals before sharing it — author/software/timestamps, embedded files, links, JavaScript, annotations, hidden layers and earlier revisions — then download a cleaned copy with the metadata and extras removed |
| Protect | /protect-pdf |
Encrypt a PDF with AES-256 |
| Unlock | /unlock-pdf |
Remove a password you already know |
Plus a 14-post blog (/blog) and trust pages (/about, /privacy).
bun install
bun run dev # http://localhost:4321Requires Bun ≥ 1.3 (bun.lock); Node ≥ 24 stays pinned in .nvmrc for tooling that
shells out to Node.
bun run check # astro check + tsc --noEmit
bun run test # vitest (unit tests, 42 tests across 9 files)
bun run test:watch # vitest in watch mode
bun run test:e2e # playwright, drives real tool flows end-to-end (7 tests)
bun run build # production build to dist/
bun run preview # serve the dist/ build locally, for e2e/PWA/Lighthouse checksbun run test:e2e builds and serves the site itself — playwright.config.ts's webServer
runs bun run build && bun run preview before the suite starts (reusing an already-running
preview server outside CI), so it always exercises a fresh production build.
There is no CI test job — run bun run check && bun run test && bun run test:e2e locally before
pushing (deploys are handled by Cloudflare's git integration, which only runs the build).
Astro 5 static build (SSG, no server at runtime)
├─ .astro pages/layouts — shell, SEO tags, JSON-LD, content (landing, tool pages, blog)
├─ React islands (client:load) — one per tool (MergeTool, SplitTool, CompressTool, EditTool,
│ WatermarkTool, SignatureTool, ProtectTool, UnlockTool, PrivacyTool), built with shadcn/ui components
├─ src/lib/pdf/* — tool logic: pdf-lib for merge/split/edit/render/privacy scan + clean, pdfjs-dist v6
│ for thumbnails and text extraction, thin client wrappers (pdfcpuClient.ts) around the worker below
├─ src/workers/pdfcpu.worker.ts — a Web Worker hosting pdfcpu (Go) compiled to WebAssembly
│ (public/wasm/pdfcpu.wasm, ~20 MB, committed as a build artifact — see wasm/pdfcpu/README.md).
│ Handles optimize/compress, watermark/stamp, signature validate+remove, and encrypt/decrypt.
│ Runs off the main thread so large PDFs don't freeze the UI.
└─ PWA offline layer (@vite-pwa/astro / Workbox) — service worker precaches the entire static
app shell (HTML, JS, CSS, fonts, images) at install time; pdfcpu.wasm is deliberately
excluded from precache (too large for most visitors to download unasked) and instead
uses a CacheFirst runtime-caching rule, so it's fetched once on first tool use and served
from cache — including fully offline — afterwards. Result: every page and every tool works
with no network connection after one visit; the site is installable as an app.
Fonts: the site UI uses a self-hosted variable font (Geist, via @fontsource-variable/geist).
PDF editing (the Edit tool) embeds Liberation Sans/Serif/Mono into exported PDFs so edited
text renders consistently regardless of what's installed on the reader's machine — see
public/fonts/LICENSE-liberation.txt (SIL Open Font License 1.1; free to embed, bundle, and
redistribute with the PDFs it produces).
The compiled public/wasm/pdfcpu.wasm and its wasm_exec.js runtime are committed so CI and
the Cloudflare deploy never need a Go toolchain. You only need to rebuild when bumping the
pdfcpu version — see wasm/pdfcpu/README.md for the pinned version, the exported JS globals,
and (important) the cache-busting procedure: pdfcpu.wasm is served with a 1-year immutable
cache header and is not content-hashed, so overwriting it in place won't bust caches for
existing visitors — rename the file and update the fetch URL instead.
cd wasm/pdfcpu
go mod tidy # only if bumping the pdfcpu version
make build
node smoke.mjsThe build output (dist/) is a plain static site: no server code, no database, no runtime
dependencies. Serve it from any web server and every tool works.
git lfs install && git clone https://github.com/murugu-21/localdobe.git && cd localdobe
docker build --build-arg SITE_URL=https://pdf.example.com -t localdobe .
docker run -d -p 8080:80 localdobe # or: bun install && bun run build, then serve dist/See SELF-HOSTING.md for the full guide: Git LFS (the WASM engines and the orientation
model live there), cache headers for nginx/Caddy/Netlify, opt-in analytics, and the handful of
values to change so your copy doesn't point at localdobe.com.
localdobe.com itself deploys to Cloudflare Workers static assets (wrangler.jsonc) via
Cloudflare's direct git integration on every push to main; that setup, plus the PostHog
proxy and source-map upload, is documented in DEPLOY.md.
localdobe is free, ad-free, and has no paid tier — nothing about a tool that runs entirely in your browser needs an account or a subscription. If it saved you a download or a sketchy upload, you can fund the time that goes into it:
Sponsorship keeps the domain renewed and the tools maintained. It never buys features behind a paywall — everything here stays free for everyone.
Astro 5, React 19 islands, Tailwind CSS v4, shadcn/ui, pdf-lib, pdfjs-dist v6, pdfcpu v0.14.0
(compiled to WASM), Vitest, Playwright, @vite-pwa/astro, deployed on Cloudflare Workers.