A few months ago I wrote here about building a 209-page sauna site without knowing how to code.
That experiment did not stay one site.
It became 12 independent buying guides for saunas, cold plunges, hot tubs, heat pumps, home batteries, generators, EV charging, water filters, greenhouses, backyard offices, air conditioning, and longevity.
You can see the network at The Guide Guy.
I am still not a developer. I use AI tools to help me implement things. But I am responsible for the decisions, the operating model, and all the mistakes below.
The surprising part was not generating another site. That became easy quickly.
The hard part was keeping 12 small sites honest, deployable, measurable, and different enough to deserve their own existence.
Why I did not make it one monorepo
Each guide is its own repository and its own Vercel project.
That was partly accidental. Sauna Guide came first, and the other sites were cloned from it. But the separation has been useful:
- one broken build does not block every site
- each site can have its own brand, content rules, and deployment history
- a weak niche can be frozen without changing the stronger sites
- I can sell or hand off one property later without untangling a shared application
The cost is drift.
Every shared fix has to be applied deliberately. Environment variables diverge. One clone keeps an old CTA. Another has the wrong analytics key. A third looks healthy locally but deploys from the wrong commit.
So I stopped treating the code template as the product.
The operating system became the product.
Problem 1: pnpm tried to be too helpful
All projects live under one parent workspace on my machine. That made dependency installation look simple, until a site started resolving modules against the parent workspace instead of its own repository.
The result was a build that worked in one context and failed in another.
The boring fix was the right one: install inside each guide with pnpm install --ignore-workspace when an install is actually needed.
No abstraction. Just one explicit rule in the runbook.
Problem 2: a successful deploy was not always the production deploy
Vercel could report a deployment as Ready while the production domain still pointed at a different deployment.
I also hit an author-identity problem. A commit could be technically valid but fail the production workflow because the Git author did not match the expected account.
Now every deployment check asks two different questions:
- Did a deployment finish successfully?
- Does the production target point to the exact commit I intended to ship?
Those are not the same fact.
This distinction sounds obvious after you learn it. It was not obvious while I was looking at a green status badge.
Problem 3: one invisible newline broke shared configuration
Some environment values were added with a shell command that included a trailing newline.
The value looked right in a dashboard. It was not right in the application.
The network rule is now to pass exact values with printf, not echo, and verify what production actually uses before changing local files.
This is a tiny lesson, but tiny lessons become expensive when copied across 12 sites.
Problem 4: shared analytics created shared confusion
The network uses a small number of analytics projects because the free plan has limits. Several domains therefore report into the same project.
That only works if every report filters by hostname.
At one point a local environment file pointed a site at the wrong analytics project while production was already correct. Editing production based only on the local file would have made the real system worse.
The fix was procedural again:
- verify the production environment
- inspect real incoming events
- filter every report by domain
- treat local configuration and deployed configuration as separate evidence
Problem 5: internal linking became a quality problem
Twelve related sites make it tempting to build an all-to-all link mesh.
That would be easy to automate and mostly useless to readers.
Instead, links need to answer the next decision in the same project.
A heat pump article may naturally link to a guide about home electrical capacity. A greenhouse article may link to water quality for a well. A random sauna article does not need links to eleven sister sites.
I added an audit that checks whether approved links resolve, whether destinations repeat too often, and whether a site has become isolated. The audit can find structural gaps, but it cannot decide whether a link helps a human. That still needs judgment.
The daily health report matters more than the template
The most useful shared code is not a page component.
It is a daily report that checks the boring things:
- production domains
- search visibility
- analytics events
- AI referrals
- leads
- content-rule violations
- broken or suspicious cross-site links
I used to think scaling meant making it faster to create another site.
Now I think scaling means making it harder for an existing site to lie about being healthy.
What I would do differently
I would build the operating checks earlier and clone later.
I would also spend less time thinking about the number of pages. Generic content is not a moat. The useful assets are current decisions, real quote data, honest verdicts, and relationships with people in each market.
The technical system should make those things easier to maintain. It should not become an excuse to build more infrastructure.
That is the biggest lesson from turning Sauna Guide into a network that also includes projects like Heat Pump Guide:
The clone script creates supply.
Trust, distribution, and operational discipline create the business.
I am still learning all three.
Top comments (0)