# What deploying my garden taught me about routing

The garden is live. Getting it there taught me something I had not thought about while building it locally: a single-page app and its own build output can quietly compete for the same URLs, and the dev server is too forgiving to tell you.

## The collision

The compiler wrote its JSON into `public/garden/`. The app reads notes at `/garden/<slug>`. Locally, both worked, so I never questioned it. But a static host resolves the filesystem before it applies a rewrite, and `/garden` was a *real directory* with no `index.html` in it. So the request matched something, found nothing to serve, and never fell through to the app. The garden listing, the most-used page on the site, would have 404'd in production while working perfectly on my machine.

I found it by refusing to trust the dev server: I served the built `dist/` the way the host would, filesystem first and rewrite second, and walked every route. The fix was not a clever rewrite rule. It was removing the ambiguity, moving compiled data to `/garden-data/` so app routes and build output can never shadow each other.

## What I'd tell myself before the next deploy

* Reserve a namespace for build output on day one; do not let it share a prefix with a route.
* Exercise the production bundle under production routing semantics before pushing, not after.
* A passing dev server is evidence about the dev server, and nothing else.

This note is also the first real test of the thing I built: it reached the live site by being a file in a folder, with no other change to the project. That was the whole promise of [the compiler](/garden/build-time-content-compiler) and of [the garden itself](/garden/this-digital-garden). If publishing had needed anything more than a commit, the design would have been wrong.

The habit of checking the built artifact rather than the friendly local one is the same instinct that [Spec-driven development with OpenSpec and AI agents](/garden/spec-driven-development-with-openspec) enforces on the other end: decide what the system must do, then go and verify it actually does that, in the place it really runs.
