Skip to content
Nuvo Code Nuvo Code
← SHEET 08 — ENGINEERING
REV B
ENGINEERING · · 5 MIN READ

Why We Don't Use a Monorepo (And What We Do Instead as a Solo Developer)

Monorepos look attractive when you're running multiple products. Here's why we chose a different approach, and what that actually looks like in practice.

Mehmet Özer Özdaş · UPDATED 01 Jul 2026

At some point, every developer running multiple products asks the same question.

Should I put everything in one repository?

The argument makes sense on paper.

Shared code in one place. Atomic commits across products. Unified tooling. One CI pipeline to rule them all.

I spent a long time convinced this was the right direction.

Then I tried it.

The Problem With Monorepos for Solo Developers

Monorepos were designed for large teams with shared codebases.

Google uses one. Meta uses one. Airbnb uses one.

The common thread is teams — hundreds of engineers working on overlapping systems who need coordinated tooling to manage dependencies across a single codebase.

That’s not what a solo developer running multiple independent SaaS products looks like.

The problems surface quickly.

A Flutter mobile app and a Laravel backend don’t share build tooling. A marketing site and an API don’t share deployment pipelines. A consent management platform and a layer management product don’t share much code at all.

What you get isn’t unified simplicity.

What you get is one repository that contains four completely different technology stacks, each with its own dependencies, its own build process, and its own deployment requirements — all tangled together.

A monorepo reduces coordination overhead between teams. A solo developer has no coordination overhead to reduce.

What I Actually Need

Running multiple products solo creates a different set of constraints.

Deployment independence. When I ship a fix to Nuvo Consent, I don’t want Nuvo Layer’s pipeline to run. Changes should be scoped to the product they affect.

Product isolation. If one product has a broken test suite, it shouldn’t block another product from deploying. Each product lives or dies on its own terms.

Cognitive clarity. Context switching between products is already expensive. Opening a single repository and seeing six different products interleaved makes it worse, not better.

Simple operations. As a solo developer, I don’t have a platform team maintaining custom tooling. Whatever approach I use needs to work without significant overhead.

None of these are well served by a monorepo.

What We Do Instead

Each product gets its own repository.

Nuvo Consent has its own repo. Nuvo Layer has its own repo. Foundrail, Regly, the company website — all separate.

This isn’t a revolutionary decision. It’s the default.

The question is how to manage what’s actually shared.

Shared Auth Layer

Authentication is the one thing every product genuinely shares.

Rather than duplicating auth logic across repositories, we use a single managed authentication provider — Clerk — that all products integrate against independently.

Each product connects to the same auth layer. Users can exist across products without any repository-level coupling.

No shared code. No shared repository. Just a shared service.

Shared Design Tokens

Visual consistency across products matters without requiring a shared component library.

We maintain design tokens — colors, typography, spacing, radius — as a documented standard rather than a published package.

Each product implements them independently.

This trades a little consistency enforcement for a lot of simplicity. For a solo developer, that trade is almost always worth it.

Operational Standards, Not Shared Code

The things that are consistent across products aren’t code.

They’re decisions.

How deployments are structured. How monitoring is configured. How environment variables are named. How documentation is organized.

These live in internal documentation, not in a shared package that every product has to import and update.

The Actual Trade-offs

I’m not suggesting this approach is perfect.

There are real costs.

No atomic commits. A change that touches two products requires two pull requests. Sometimes this matters. Most of the time it doesn’t, because products rarely need to change together.

Duplicated configuration. CI pipelines, linting rules, environment variable patterns — these exist in every repository. Updating a shared standard means updating multiple repos.

No automatic dependency propagation. If a shared service changes its API, every product that uses it needs to be updated manually.

These are real friction points.

But for a solo developer running independent products, they’re manageable friction. The alternative — a monorepo that fights every tool you’re using — is not.

When a Monorepo Would Make Sense

I’m not against monorepos categorically.

If I were running a single product with a frontend, backend, and shared component library all deployed together, a monorepo would be the right call.

If I had a team working across overlapping systems and needed coordinated dependency management, a monorepo would be the right call.

But that’s not the situation.

The situation is multiple independent products, built on different stacks, deployed independently, maintained by one person.

For that situation, the simplest thing that works is the right thing.

Multiple repositories. Shared services where genuinely useful. Documented standards instead of shared code.

It’s not elegant. It doesn’t make for an interesting architecture talk.

But it ships.

developer experiencearchitecturesolo developerlaravelflutter

RELATED NOTES