DEV Community

Cover image for Invoice Purgatory: How I escaped the monthly click-fest by building my own invoicing tool
Eli Payano
Eli Payano

Posted on

Invoice Purgatory: How I escaped the monthly click-fest by building my own invoicing tool

Every month, same ritual. Open the browser, navigate to the invoice generator, update the date, bump the invoice number, change the line item description, download the PDF, open my email, attach it, send it.

It's maybe five minutes. But it's five minutes of pure purgatory.

So I built my own. And I kind of love it.

A little context

I'm a Senior Support Engineer; I'm not a full-blown developer, but I know how to build things — and there's always the good ol' Claude Code to help me ship faster. This project started as a weekend idea and turned into something I actually use every month.

My first instinct

My first instinct was to just replicate the online invoice generator — a clean web UI where I could fill in the details, hit a button, and get a PDF in my inbox. Full control over the template, no third-party tool, no clicking through the same form every month.

And I built that. It works great. It remembers everything I've ever typed into it, has a light/dark theme, validates the recipient email, and sends the PDF directly to finance with one click.

But halfway through I realized — I live in the terminal. Why am I opening a browser every month to fill out a form when I could just type invoicer and answer three prompts?

So the CLI became the real deliverable.

What I actually use

invoicer
Enter fullscreen mode Exit fullscreen mode
  invoicer CLI

? Invoice number: 5
? Month: May 2026
? Amount (USD): 1000000000 USD
? From: Eli Payano
? Bill to: Company XYZ
? Bank account: BANK USD
? Send to: finance@company.com
? Send via email? Yes

  Generating PDF...
  Sending email...

  ✓ Invoice sent to finance@company.com
Enter fullscreen mode Exit fullscreen mode

That's it. The month defaults to the current month. The due date is automatically set to the last day of that month. My sender details, client details, and bank accounts are all saved in an invoice.config.json — I pick them from a list with arrow keys. The only things I ever change are the invoice number, the month, and the amount.

From zero to sent in about 5 seconds.

How it works

The stack is a pnpm monorepo with four packages:

  • web — React + Vite invoice UI
  • api — Express backend
  • cli — the CLI tool
  • shared — the HTML template, PDF generation, and email sending

The shared package is my favorite part. The HTML invoice template lives there once and is used by both the web app and the CLI. Puppeteer converts it to a PDF, Resend delivers it. Change the template in one place, everything updates.

For PDF generation I went with Puppeteer over something like jsPDF because it renders HTML exactly like a browser would — fonts, layout, everything. The output looks exactly like the web UI preview.

For email I went with Resend over Gmail + Nodemailer because the developer experience is just better. One API key, done. No App Passwords, no OAuth, no wrestling with Google's security settings.

The web UI uses IndexedDB instead of localStorage for caching the draft — more storage, async API, survives browser storage pressure. Every keystroke is saved automatically so I never lose a half-filled invoice.

What I love about it

I own the whole thing. The template is mine. The PDF looks exactly how I want it to look. There's no "upgrade to Pro to remove the watermark." There's no terms of service change that breaks my workflow. It runs locally, it's fast, and it does exactly one thing well.

And honestly — the fact that I can type invoicer from anywhere on my machine and have an invoice in someone's inbox less than 5 seconds later still makes me happy every time.

If you're the kind of person who'd rather stay in the terminal than open a browser, and you're still using online tools that force you to context switch — maybe this is a good place to start.

What's next

I just published it to npm — npm install -g @eli7pm/invoicer and you're good to go.

Try it out and let me know what you think in the comments.

The full source is on GitHub: github.com/eli7pm/invoicer

Top comments (0)