Gateway & Worktrees
The gateway is a local nginx reverse proxy that maps a friendly domain — say
api.local — to whichever service currently owns it. Because denvig treats a
project as a family of git worktrees, you can run the same service in several
checkouts at once and move a domain between them on demand, without editing config
or restarting nginx.
This guide explains the model and walks through the common workflows.
The model
Section titled “The model”A few rules make the rest of the guide predictable:
- A domain has one owner at a time. The gateway routes the domain to exactly one running service. Whoever currently holds it is the owner.
- Services run per-worktree. The
apiservice in yourmaincheckout and theapiservice in afeature/xworktree are distinct running services that can be up simultaneously — on different ports. - Domains are claimed at start. A service routes through the gateway using the
domains in its
httpconfig. You can override those for a single start with--domains, which takes over the domain from any current owner. - Ownership is handed back on stop. When a service that claimed a domain via
--domainsstops, the domain is handed back to its previous owner if that owner is still running.
A service with a domain
Section titled “A service with a domain”Start with a service that declares a domain in its .denvig.yml:
services: api: command: pnpm dev cwd: apps/api http: port: 3000 domain: api.local secure: trueStarting it in the primary checkout claims api.local:
denvig services start apihttps://api.local now routes to this service. Confirm what the gateway sees:
denvig gateway statusRunning the same service in a worktree
Section titled “Running the same service in a worktree”Suppose you create a git worktree for a feature branch:
git worktree add ../denvig-feature feature/xDenvig sees feature/x as another worktree of the same project. You can start its
copy of the api service alongside the one already running in main. By default
it would contend for the same configured domain, so be explicit about intent.
Option A — run it on a port only
Section titled “Option A — run it on a port only”To bring the feature copy up without touching api.local, start it with
--no-domains. It runs on its own port and the main checkout keeps the domain:
denvig services start api --worktree feature/x --no-domainsBoth copies are now running. List them to see the tree:
denvig services listOption B — swap the domain to the worktree
Section titled “Option B — swap the domain to the worktree”To point api.local at the feature worktree’s service instead — while the main
copy keeps running — claim the domain explicitly:
denvig services start api --worktree feature/x --domains api.localThe feature worktree is now the owner of api.local; the main copy keeps
running on its port but no longer holds the domain. Your browser hits the feature
branch at the same URL, with no nginx edits and no restart of the other service.
Swapping back
Section titled “Swapping back”Stop the feature copy and ownership is handed back to the still-running main
service:
denvig services stop api --worktree feature/xapi.local routes to main again.
A worked workflow
Section titled “A worked workflow”-
Bring up the baseline in your primary checkout — it owns
api.local:Terminal window denvig services start api -
Add a worktree for the branch you want to test:
Terminal window git worktree add ../denvig-feature feature/x -
Swap
api.localover to the feature worktree to test it at the real URL:Terminal window denvig services start api --worktree feature/x --domains api.local -
When you’re done, stop the feature copy — the domain returns to
main:Terminal window denvig services stop api --worktree feature/x
Multiple domains and CNAMEs
Section titled “Multiple domains and CNAMEs”A start can claim several domains at once — useful when a service answers on more than one hostname:
denvig services start api --domains api.local,api.testEach domain is claimed independently and each is handed back to its own previous owner on stop.
Rebuilding after config changes
Section titled “Rebuilding after config changes”If you change a service’s http settings, or the gateway and your running
services drift apart, reconcile and rebuild every nginx config:
denvig gateway configureDoing this from the SDK
Section titled “Doing this from the SDK”The same workflow is available programmatically — claim domains per start with
service.start({ domains }):
const project = await denvig.projects.retrieve('github:marcqualie/denvig')
// Swap api.local to the feature worktree's serviceconst feature = await project.services.retrieve('api', { worktree: 'feature/x' })await feature.start({ domains: ['api.local'] })
// Hand it back by stopping the feature copyawait feature.stop()
// Inspect or rebuild the gatewayawait denvig.gateway.status()await denvig.gateway.configure()See the SDK Gateway and SDK Services references for the full API.