कागज़Kagazpaper tools

MIT licensed · no build step · no framework

Contribute

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.

Getting set up

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.

How the code is laid out

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:

  1. One tool is one HTML file. Markup, styles specific to it, and its logic all live together. You should be able to understand a tool without opening anything else.
  2. Nothing may be fetched from another origin. No CDN, no font service, no analytics. The entire premise of Kagaz is that opening it makes no network requests, and a contributor adding a Google Font would quietly break that.
  3. PDF logic goes in 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.

Adding a new tool

  1. Copy merge-pdf/index.html to your-tool/index.html. It is the simplest of them.
  2. Change the title, description, canonical URL and the copy below the fold. The slug should be what a person would actually type into a search box — rotate-pdf, not rotator.
  3. Put the actual PDF manipulation in shared/ops.js as a function that takes bytes and returns bytes.
  4. Add a card to the grid on the landing page and a link in every tool's footer list.
  5. Add a case to tests/stress.mjs.

Things worth building

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:

Harder, and more interesting

Please don't

Reporting something without opening an issue

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.

Running the checks

npm run check

Three suites, and none of them need a single dependency — clone the repository and they run:

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.

Buy me a chai

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.

Who made this

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.