By Joel Dare ⟡ Written March 1, 2026
There’s a specific anxiety that comes with building financial tools: the moment you add a server, you’ve taken on responsibility. You now hold user data, you’re a target, you have uptime obligations, and you’ve introduced a dependency between someone’s daily money workflow and your infrastructure staying online.
I didn’t want any of that.
So when I built Balance Buckets — a tool that answers exactly one question, “how much is available to spend right now?” — I made it run client-side in the browser. No accounts. No sync. No backend. Just a single HTML file that stores everything in localStorage. Open it, type your balance, see what’s left after your savings buckets fill up.
I knew going in that I wanted to charge for it — I just wasn’t sure how.
The obvious problem: there’s nothing to enforce. The app has no way to phone home. It doesn’t know whether you paid. The whole premise of local-first is that your browser is the only computer involved.
My small business bank account doesn’t have envelope budgeting. As far as I can tell, no banks offer it for small business accounts — it’s a feature I’ve only found in personal banking.
I would have been happy with envelope budgeting inside a bank portal, but I couldn’t find it anywhere for business accounts. So I built a tiny standalone tool I could check in under two minutes. Enter the balance, see the buckets fill up in order, know whether the computer fund is covered before the hosting bucket, know what’s left after everything is accounted for.
Part of the reason it’s local is philosophy — I like minimalism and simplicity, and I don’t want this financial configuration data in my database. There are practical benefits too: If I have a backend, I have a potential outage on the day you actually need to check your balance. I have a database that knows your financial bucket configuration. I have a company relationship with a user who just wants a fast mental accounting check.
localStorage doesn’t have any of those problems. It’s fast, it’s private, it’s yours. The tradeoff is obvious: your data is stuck to the browser you used. Export/import covers migration but not sync across devices.
The app is a single index.html file deployed on GitHub Pages. The manifest makes it installable as a PWA. When a user asked whether it works offline and whether it checks for payment status on load — the answer to both was simple: it’s static HTML, it runs entirely in your browser, it never makes a network request during normal use.
If the app never calls home, how do you gatekeep paid features?
Short answer: you don’t. You can’t. The source is right there.
I don’t believe in DRM, so license checks and validation endpoints were never really on the table. Both feel wrong anyway — the first is security theater that annoys honest users, the second reintroduces the infrastructure dependency I was avoiding.
So I went with the shareware model.
If you’ve been building software long enough to remember shareware, you know how it worked: you distributed the software freely, it nagged you, and honest people paid. It wasn’t about enforcement. It was about trust as the business model. Some companies even quietly relied on piracy for distribution — the more copies floating around, the more people who might eventually buy.
Balance Buckets nudges you when you create a bucket beyond your fifth. That’s it. Paid users get the nudge too right now, which is a bug I’ll fix if anyone actually pays. It’s a prompt, not a lock. You can dismiss it and keep going. The software doesn’t know whether you’re a paying user or not.
I’m using Stripe pay links — literally just a URL. No code, no server-side Stripe integration, no webhooks updating a user record. Click the link, pay, done. No account required on the buyer’s side unless they already have one.
This means Balance Buckets is fundamentally a tool that works on the honor system. There’s a small note that shows how many buckets you’ve used out of the five free ones — and if you’ve gone over, it quietly reflects that too. A gentle reminder that you’re getting value. If you find it useful, I’d appreciate payment. If you don’t pay, the software still works.
There are two failure modes I was trying to avoid.
The first is building a “free” tool with no monetization, watching it become a maintenance obligation, and eventually abandoning it or adding ads. That path is well-worn and it’s not good for users.
The second is over-engineering the business model for a tool that’s genuinely simple. A license server for a local-only personal finance calculator is absurd — even if you believe in DRM and license servers. The complexity cost outweighs the revenue protection benefit by a large margin, especially at MVP stage.
The shareware model threads this cleanly. I get to find out if anyone cares enough to pay. Users get a tool that works without friction. There’s no infrastructure to maintain for the payment verification layer. And if someone finds the tool useful and never pays, they’re still a net positive — they might tell someone, they might convert later, they cost me nothing to serve.
The real question I wanted answered at launch was simpler than “will this make money” — it was “does anyone find this useful enough to pay?” If the answer is yes, I’ll know. If the answer is no, I’ve still got a tool I use myself and a clean codebase I didn’t over-complicate.
Local-first is quietly having a moment. Privacy-preserving tools, offline-capable apps, software that doesn’t require you to create an account before you can use it — these are increasingly what thoughtful users want.
But local-first creates a genuine monetization tension. The value of not phoning home is exactly the property that makes license enforcement impossible. Every solution to that tension either reintroduces a server (defeating the purpose) or relies on social contract.
I think the answer is: lean into the social contract. Be transparent about it. The users who value local-first software are often the same users who understand why you need to charge for sustainable software. Reminder prompts and pay links are unsexy but honest.
The alternative — building fake DRM for local software — is worse for everyone. It adds complexity you’ll maintain forever, it signals distrust to your users, and it doesn’t actually stop determined people anyway.
I’m shipping an MVP that trusts its users. That feels like the right call. Whether it’s the right business call, I’ll find out.
Balance Buckets is at buckets.joelryan.com. It’s a PWA, it works offline, and it answers one question fast. Five buckets free, more on the honor system.
What’s your take on shareware-style monetization for local-first tools? Is trust-based pricing a viable model, or is it wishful thinking in 2026?
Want to build your next site in pure HTML and CSS? Join the free Five-Day Neat Starter Email Course and build a lean, production-ready page before Friday.
JoelDare.com © Dare Companies Dotcom LLC