Three repos, one promise
Three modes in the product; three repos in the code. Not a coincidence. The same instinct applied twice: separate the things that move at different speeds.
Three modes in the product; three repos in the code. Not a coincidence. It’s the same instinct applied twice: separate the things that move at different speeds.
The context
The monorepo temptation is real. One clone, one issue tracker, one CI. Some companies do it well. For a solo dev, monorepos also have a clear win: atomic refactor. You can change an API and its consumer in the same PR.
But it couples falls. If backend and frontend live in the same repo, so do their releases. When I want to push a micro frontend improvement, I read a database migration on the same branch. And when I’m in a hurry, I skip one of the two.
The decision
Three separate repositories, one shared promise:
- camperroute-api. FastAPI + Postgres + Celery backend. Its own cycle. We deploy with a PR + merge to staging and another to main. No other repo holds it.
- camperroute-app. React + Vite + PWA frontend. Also its own cycle. Same trunk-staging pattern. It consumes the API via an OpenAPI contract, not through direct imports.
- camperroute-meta. Private. It holds the BMAD documentation: briefs, epics, stories, architectures, retros. Nothing deploys — it’s the logbook. Private because it’s not for consumers, not because it’s secret.
Why meta is private. It contains no secrets or sensitive data. It contains how decisions get made: open doubts, mistakes committed, honest retros. If it were public, I’d have to self-censor — and a self-censored dev document is worth zero. Keeping it private lets me write it the way I’d think it.
What it’s not
To be explicit:
- Not a microservices architecture. There is one backend and one frontend. The split is per repo, not per runtime service.
- Not three teams. I’m one person. The split doesn’t reflect an organisation; it reflects different life cycles.
- Not a manifesto against monorepos. For teams of more than 2-3 people with frequent cross-cutting refactors, a good monorepo (Nx, Turborepo, Bazel) probably pays. Here, no.
What’s next
In the next — and last — post of the series: how I observe what happens in the product without seeing the user. Sentry, yes, but with paranoid scrubbing rules. The difference between knowing something broke and knowing whose screen it broke on.