← Studio
04

On my own

Built on platforms I don’t control

Part of Cellopackcellopack.xyz

Problem
Cellopack’s value depends on signals it doesn’t own. A collector’s reputation, account ownership, identity, and marketplace history live on eBay, Instagram, X, Reddit, Facebook, YouTube, and Mercari, each a platform I don’t control, each exposing a different amount of access, and each free to change or revoke it whenever they like. Some offer clean verification through OAuth. Some offer nothing usable at all. That set the one property the whole system had to protect: it has to stay trustworthy even when the sources behind it are inconsistent or gone.
Constraints
Solo and bootstrapped, so every dependency I took on was something I would have to run alone. That set the first rule: own only what differentiates the product. It also handles real money and real identity from the start, so secure and correct could not be a later phase. And the external platforms were a moving target, ranging from a documented API to a login page and nothing else, so the design could not assume any one integration would exist or keep working.
Process
The architecture came down to three decisions. First, rent the commodity layers. Accounts, database, and serverless functions run on Supabase; payments and identity verification on Stripe and Stripe Identity; errors on Sentry; analytics on PostHog, proxied through a first-party path to reduce client-side blocking and data loss. The only thing I hand-build is the trust model, because it is the only part that differentiates the product. Second, normalize inconsistent verification. Rather than a yes or no, verification is a spectrum: confirmed instantly through OAuth where a platform allows it, routed to a human review queue where it doesn’t, with common trust states underneath so the rest of the product never has to care which path a signal came through. A platform with no API slows a member down instead of stopping them, and every new integration strengthens the system without a rewrite. Third, enforce trust at the boundaries. Money and identity changes arrive as webhooks handled on the server, not trusted from the browser; where an action must not happen twice, a ledger with a uniqueness guarantee makes it idempotent; access rules live in the database through row-level security; and state that has to stay consistent, like whether a profile is discoverable, is set by database triggers so it can’t drift from the rule in application code.
Outcome
What runs in production is a trust platform one person can actually maintain. The infrastructure underneath is mostly rented and boring on purpose; the trust model, the part worth owning, is the only thing that’s custom. And it holds the property it was designed around: when a source is inconsistent or missing, the system stays trustworthy on the signals it does have, and better access later only sharpens them. It is live, handling real payments, identity, and reputation, from a codebase small enough to hold in my head.
Lessons
The decision that mattered wasn’t the stack of vendors. It was naming what the system had to keep true, that it stays trustworthy on unreliable inputs, and building every layer in service of that. You cannot make a platform expose an API it doesn’t have, so I treated every outside signal as fallible and designed the system to still be right in aggregate. Renting everything else kept the amount I had to own small.