I do freelance dev work on the side, and every month I was opening a "serious" invoicing SaaS just to generate one HTML page with a line-item table. The onboarding alone took longer than writing the invoice by hand.
So I built freelance-invoice-cli: a tiny Node script that takes a JSON file and spits out a clean, printable HTML invoice. No React, no PDF library, no build step - just template literals and escaping.
Why zero dependencies
Three reasons, in order of how much they actually matter:
- An invoice template does not need a framework. It is a table and some text.
- Every dependency is a thing that can break, get deprecated, or ship a supply-chain surprise. For a tool that touches money, I wanted to be able to read the entire codebase in five minutes.
- npm install taking 15 seconds instead of 400ms is a real tax when you just want to bill a client before you forget.
What it actually does
npx freelance-invoice-cli invoice.json > invoice.html
Input is a plain JSON file with from/to/items/currency fields - each item has a description, qty, and rate. Output is a self-contained HTML file you can open, print to PDF from the browser, or email directly.
All user-supplied strings go through a single escape function before they touch the template. I learned the hard way, on a different project, that "just interpolate it, it's your own data" stops being true the moment a client's company name has an ampersand in it.
Where it lives
Repo: github.com/kleogeos/freelance-invoice-cli (MIT, 7 tests, no deps in the render path)
If you want more than one tool - time tracking, currency conversion, a late-fee calculator, an NDA template - I bundled the ones I actually use into a small Freelancer Starter Kit (link in my GitHub profile). The invoice CLI itself is free and will stay free; the kit is just the "I don't want to assemble six repos myself" version for $9.
Happy to answer questions about the escaping approach, or trade zero-dep war stories in the comments.
Top comments (0)