MIT licensed · no build step · no framework
Kagaz is deliberately boring to work on. There is no toolchain, no bundler, no
node_modules to install before you can see a change.
Clone it, open a file in your browser, and you are developing.
git clone https://github.com/namastevis/kagaz.git
cd kagaz
python3 -m http.server 8000
# open http://localhost:8000
The small web server is only needed because pdf.js loads its worker as a separate file,
which browsers block on file://. Any static server will do.
index.html the landing page
roadmap/index.html what exists, what is coming, what never will
merge-pdf/index.html one tool, one self-contained file
split-pdf/ compress-pdf/ pdf-to-jpg/ jpg-to-pdf/
organize-pdf/ rotate-pdf/ crop-pdf/ page-numbers/
watermark-pdf/ sign-pdf/ scan-to-pdf/ redact-pdf/
certificate/index.html Certificate Press
shared/kagaz.css every page shares this stylesheet
shared/kagaz.js browser helpers: drop zones, downloads, canvas, thumbnails
shared/ops.js the PDF logic — deliberately DOM-free
vendor/ pdf-lib, pdf.js, JSZip, fontkit — vendored, never a CDN
tests/stress.mjs throws deliberately broken PDFs at shared/ops.js
tests/verify.mjs fails the build if any page loads an external asset
Three rules keep it that way, and they are the only ones:
shared/ops.js, not in the page. That file has no DOM references, so it runs in Node and can be tested. Anything needing a canvas is passed in as an argument.merge-pdf/index.html to your-tool/index.html. It is the simplest of them.rotate-pdf, not rotator.shared/ops.js as a function that takes bytes and returns bytes.tests/stress.mjs.The full list lives on the roadmap, which also records what will never be built here and why. Everything in its “being built” section is unclaimed.
Good places to start, roughly easiest first:
shared/kagaz.css, so this is mostly one prefers-color-scheme block.CompressionStream makes re-deflating them possible.Not everyone who finds a bug here writes code, and a GitHub account should not be the price of telling me something is broken. The report page offers three routes — email, a post on X, or a prefilled GitHub issue — and fills in the browser details for you, since that is the part people cannot be expected to know.
Nothing on that page sends anything by itself. It builds a link and waits for you to press it.
npm run check
Three suites, and none of them need a single dependency — clone the repository and they run:
npm run lint — the project's own rules. No network APIs, no persistent
storage, no assets from another origin, every inline script parses, every tool page links to
the report page.npm run verify — the site: dead links, metadata, mobile viewport, tap targets.npm test — the PDF engine against deliberately awful files: zero-byte,
truncated, a JPEG renamed to .pdf, encrypted, two thousand pages, impossible
page sizes, seven-step chains.
The linter is the one worth understanding. It does not check style — it checks that the
promises on the front page still match the code. Add a fetch, or reach for
localStorage, and the build fails telling you which claim you just broke. That is
deliberate: those two lines are the entire product, and they are far too easy to erode by
accident.
ESLint is configured but optional, and CI treats it as advisory. Style should never be the reason a contribution is turned away.
There is also an in-browser test page covering what Node cannot —
the canvas codec, createImageBitmap, and rendering. Open it after any change to
the shared helpers.
Kagaz took a lot of evenings to build and costs almost nothing to run — which is exactly why it has no limits, no accounts and no ads, and why it will stay that way whether or not anyone ever sends me anything.
There is nothing here that needs funding. A chai is just a way of saying that an hour of your time got saved by a few of mine.
That Razorpay link is the only outbound link on this site that leads anywhere commercial, and nothing loads from it unless you click. No payment script runs on these pages.
I'm Amit Jena — an Accidental Designer. Mathematics and computer science by training, pulled sideways into design, and now mostly building data-heavy things: dashboards, document tools, anything that turns a pile of numbers or paper into something a person can use.
Nearly all of it is open source, and I'd rather it stayed that way. Partly because a tool asking for your trust should let you check it, and partly because I have never learned more from anything than from reading other people's code.