For the first year of running Co Digit as a two-partner studio, our entire back office lived in a single Google Sheet. One tab for clients, one for who had paid what, a third for the running profit split between the two of us. It was free, it was instant, and it worked — right up until the afternoon we both opened it, looked at the same row, and read two different numbers out loud.
Nobody had done anything wrong. One of us had edited a cell while the other was mid-calculation, a formula had quietly stopped covering a client added two weeks earlier, and a payment had been marked "received" by the partner who sent it rather than the one who got it. None of these are spreadsheet bugs. They are what a spreadsheet does when you ask it to be the system of record for money shared between two people. That afternoon we decided to build the thing the sheet had been pretending to be. We called it Bridge.
The Three Things a Spreadsheet Could Not Do
Once we wrote down what we actually needed, three problems separated themselves from the rest, and none of them were really about formulas.
The first was money. We bill each client, take a development fee off the top, and split the remaining profit on a per-client ratio — sometimes 5:5, sometimes 4:6, occasionally something custom. A spreadsheet can compute that all day. What it cannot do is stop one partner from marking a payment settled before the other has actually watched the cash land in an account.
The second was time. Every client lives in a different calendar — one on Google Workspace, one on Outlook, two more on whatever their project tool exports. We were opening four calendars to answer the single question "what is due this week," and inevitably missing the one we forgot to check.
The third was the daily standup. With two developers and a rotating contractor, we wanted one place to post what we did, what was blocking us, and what was next — without it dissolving into a Slack thread that scrolls into the void by Thursday afternoon.
Why We Didn't Just Buy Something
The obvious objection is that all three problems are solved products. There are agency-management platforms, there are billing tools, there are standup bots. We tried several of each.
The issue was never capability. It was that every one of them is priced and designed for a team of fifteen, not a partnership of two. We would have paid three monthly subscriptions, learned three different data models, and then glued them together by hand anyway, because none of them knew the other two existed. For a studio our size, the integration tax was higher than the cost of building.
There was also a quieter reason. The numbers in question are our own income. Handing the single source of truth for how two people divide their money to a third-party service — with its own export limits, its own outages, and its own private definition of "deleted" — felt like exactly the wrong corner to cut to save a weekend.
The Decision That Shaped Everything: Trust the Database, Not the UI
The first real architectural choice set the tone for the rest. When you build an internal tool, the lazy path is to enforce the rules in the interface — hide the buttons a user should not press, and trust that nobody opens the network tab. For a public marketing page, fine. For a console holding revenue figures and per-developer updates, not fine.
So every access rule in Bridge lives in the database, as Postgres row-level security, rather than in the front end. A developer can only read and edit their own standup entries because the database itself refuses to return anyone else's rows — not because a script in the browser politely hides them.
-- A developer can only touch their own standup rows.
create policy "own_standups"
on standups for all
using ( auth.uid() = developer_id )
with check ( auth.uid() = developer_id );
The difference is not theoretical. With this policy in place, it does not matter what the front end sends. A crafted request asking for another developer's updates comes back empty, because the filter lives one layer below anything the browser can reach. The interface became a convenience sitting on top of a database that was already safe, instead of the only thing standing between a user and data they should never see.
Money Needs Two Confirmations, Not One
The spreadsheet's original sin was that a single click could change a shared number. So in Bridge, settling a payment is deliberately not a single action.
When profit moves between partners, the sender marks it sent and the receiver marks it received. The ledger entry only turns green — only counts as settled — when both confirmations exist. Until then it sits in a visible in-between state that neither person can quietly resolve alone.
This sounds like a small UI detail. In practice it removed an entire category of disagreement. There is no longer a version of events where one partner believes a transfer happened and the other is still waiting, because the system will not call it done until both have said so. The number on the screen is now the one thing we never have to re-check against each other's memory.
The Calendar Problem Nobody Talks About
Merging calendars sounds trivial until you try it. Every client platform can export an iCal feed, but each of us was subscribing to those feeds individually, on our own devices, in our own apps. Add a client and you had to remember to send the new link to your partner, who had to remember to add it before it would show up.
Bridge collapses that into one feed. It takes every client's Google or Outlook iCal URL, merges the events on the server, and serves a single subscribe link. You subscribe once, on every device you own, and a client added in the console simply appears — no second step, no forwarded link, no "did you add it yet."
The lesson here was about where to put the work. We could have asked each person to manage their own subscriptions and saved ourselves the merge logic entirely. Doing the merge once, centrally, meant the humans had to remember nothing. Any time you can move a recurring chore from a person to a server, you should — the server does not forget on a busy Friday.
Built on a Free Tier on Purpose
Bridge runs on a free Supabase project and a free Netlify site. That was not a cost-cutting accident — it was a constraint we set on day one, for two reasons.
The first is honesty about scale. A two-partner studio does not generate the kind of load that costs money on these platforms, and pretending otherwise would have pushed us to over-engineer. Staying inside the free tier forced every decision to stay proportional to the actual problem in front of us.
The second is that it made the tool portable. Because there is nothing exotic in the stack — Postgres, row-level security, a static front end, a handful of iCal feeds — anyone running a similar small studio can stand up their own copy in an afternoon. We built Bridge for ourselves, but the white-label version costs nothing to run, which means the design was never quietly locked to our particular setup.
What We Would Tell Anyone Building an Internal Tool
We are not in the business of selling agency software, and Bridge is not a product we are pitching. It is the tool we needed, built once, in public. A few of the choices held up well enough to pass on.
Build for the size you are, not the size you imagine. Every feature in Bridge is scaled to two partners and a contractor, and that constraint is exactly what made it shippable in a weekend instead of a quarter.
Put the rules where they cannot be bypassed. Enforcement in the database rather than the interface is the single decision we are most glad we made, and it cost almost nothing up front.
When something involves shared money, make agreement explicit. The dual-confirmation ledger is the least clever part of the whole system and the part that has saved us the most grief.
The Quiet Test
The Google Sheet still exists, by the way. We kept it around for a few weeks after Bridge went live, out of pure habit, glancing at it to make sure the new system agreed with the old one. It always did — and then one day we noticed we had not opened it in a month.
That is the quiet test for any internal tool. Not whether it launches, not whether the demo looks sharp, but whether it makes the thing it replaced boring enough to forget. The sheet that once gave two partners two different numbers is now just a tab we never click. That, more than any feature, is how we know Bridge worked.