Inspiration
More than 70% of freelance invoices are paid late at least sometimes. Almost none of that is refusal — it is drift. An invoice nobody opened. A follow-up nobody wanted to write.
Bangladesh has one of the largest freelance workforces on earth, and nearly all of that work is billed to clients abroad. Every one of those freelancers has to decide, alone and usually while annoyed, how impolite they are willing to be with someone who might hire them again. So the follow-up gets delayed, then softened, then skipped entirely.
Baki (বাকি — Bangla for "outstanding, still owed") exists because that is a scheduling problem people solve badly, not a writing problem.
What it does
You create an invoice and get a link. The client opens a clean document with a pay button. Once the due date passes, the follow-ups escalate on a schedule you chose in advance.
Four things separate it from an invoicing tool:
The tone is decided before you are annoyed. Three schedules — gentle, standard, relentless — across four registers: CORDIAL, FIRM, COLD, FINAL. One calm decision when you send it, instead of four uncomfortable ones later.
The client can answer back. Instead of paying today, they can commit to a date. The ladder pauses completely until it passes, and that silence is exactly what makes committing more attractive than ignoring. Miss the date and the ladder does not resume where it paused — it resumes one register colder, because a broken promise is worse than an unanswered invoice.
You can see if they opened it. Every invoice counts client opens. The gap between unseen and ignored is the gap between waiting and chasing.
It shows what actually reaches you. Payoneer does not let users hold a balance in Bangladesh; money arrives through Payoneer and is withdrawn via a partner such as upay. So outstanding totals carry an estimate of what survives the fees. Here, the invoice total is not the number that matters.
Baki writes every follow-up but deliberately does not send it. Freelancers in this market chase clients on WhatsApp, from their own number, in their own thread. So it hands you the exact wording, ready to copy or open in WhatsApp or email. Delivery was never the hard part — deciding what to say and when was.
How I built it
Next.js 16 App Router with server actions, TypeScript, Tailwind, Neon Postgres, deployed on Vercel. OpenRouter writes the reminder wording, with template fallbacks so the product behaves identically with the model switched off.
Two decisions shaped everything else. Escalation state is derived from the due date and tone at render time, never stored — so the same invoice always produces the same ladder and there is no scheduler state to drift out of sync. And there are no accounts: invoices you create are remembered per-device in localStorage and their live status is fetched by id, which gives a freelancer their history back with no login and nothing shared between visitors.
Public writes are rate limited in Postgres rather than Redis, since adding a service for a few writes an hour was not worth it.
Challenges I ran into
Stripe accounts cannot currently be created from Bangladesh, which the organisers flagged
in advance. Rather than fake an integration, the payment flow is built with the real shape
and clearly labelled test mode — swapping in a live Stripe Payment Link is a one-line
change in lib/payment.ts. Nothing in the interface implies a live integration.
Building history without accounts was the other one. A dashboard normally implies a login. localStorage plus id lookup solved it, with a demo-data fallback so a first-time visitor never lands on an empty page.
Accomplishments that I'm proud of
The promised-date mechanic. Chasing is one-directional, and one-directional systems fail — you push, they ignore, you push harder. Giving the client a way to respond turned a nagging tool into a negotiation with structure.
Also that the product is honest about its limits. The Stripe constraint, the fee estimate being published rates rather than a quote, and the deliberate choice not to send email are all stated plainly rather than papered over.
What I learned
The interesting problem was never payments. It was that the uncomfortable part of freelance work is not the invoice, it is the follow-up — and that discomfort is solved by moving the decision earlier, not by writing better copy.
What's next for Baki
Scheduled delivery via Inngest, late-fee accrual, deposits and partial payment, and BDT shown alongside USD.
Built With
- neon
- nextjs
- openrouter
- postgresql
- react
- server-actions
- stripe
- tailwindcss
- typescript
- vercel

Log in or sign up for Devpost to join the conversation.