Guide

Custom Domains

stack defaults new projects to .localhost because it resolves to loopback for free — no setup, no hosts file, no admin rights, since it's RFC 6761-special-cased. Coming from Herd or Laragon, you might prefer the shorter, more familiar .test instead. That works too — it just needs one one-time step first.

Why this needs a step at all

[project].domain is fully free-form in stack.tomldomain = "myapp.test" works today with zero code change, since Caddy (the actual router stack drives) doesn't care what string it's given. The gap is DNS resolution: unlike .localhost, .test is reserved by RFC 2606 but your OS doesn't automatically route it to loopback. Herd and Laragon don't get this for free either — they quietly automate it for you (writing per-project entries into the hosts file, or running their own resolver). This page is that same one-time automation, done manually, once, for every .test subdomain at once.

Windows — Acrylic DNS Proxy macOS/Linux — dnsmasq (stack not yet shipped there)

Windows: Acrylic DNS Proxy

Acrylic is a small local DNS proxy that supports wildcard entries in a custom hosts-like file. Needs admin rights, one-time.

1

Install Acrylic

Download and run the installer from the official Acrylic DNS Proxy page.

2

Add a wildcard entry

Open AcrylicHosts.txt (from the Acrylic UI's menu, or directly under its install folder) and add:

AcrylicHosts.txt
127.0.0.1 *.test

Restart the Acrylic service afterward (from its tray icon or Windows Services) so the change takes effect.

3

Point your network adapter at Acrylic

Network and Sharing Center → Change adapter settings → your active adapter's Properties → Internet Protocol Version 4 (TCP/IPv4) → Properties → set Preferred DNS server to 127.0.0.1. Do this for every adapter you actually use (Ethernet and Wi-Fi both, if you switch between them).

From here, any *.test domain resolves to loopback the same way *.localhost already did — including domains from projects you haven't created yet, since it's a wildcard, not a per-project entry.

macOS/Linux: dnsmasq

stack only ships Windows builds today — this section is here for when that changes, and for anyone running stack's source build on these platforms in the meantime.

1

Install and configure dnsmasq

terminal
$ brew install dnsmasq
$ echo 'address=/.test/127.0.0.1' >> $(brew --prefix)/etc/dnsmasq.conf
$ sudo brew services start dnsmasq
2

Register .test as a resolver domain

terminal
$ sudo mkdir -p /etc/resolver
$ echo "nameserver 127.0.0.1" | sudo tee /etc/resolver/test

macOS routes any *.test lookup through /etc/resolver/test to dnsmasq from here on, system-wide — no per-app configuration.

Avoid .dev (a real, ICANN-delegated TLD Google owns) and .local (claimed by Bonjour/mDNS on macOS) for this — .test is the one actually reserved for exactly this purpose.

Next

Once your TLD resolves, set it per-project the normal way: domain = "myapp.test" in stack.toml's [project] section, or answer the domain prompt with it when running stack new/stack init. See the Manifest Reference for the full [project] section.