Ports, the LAN, and the phone in your pocket
Small conventions that stop 'why is this app dead' from happening weekly
The agent starts a dev server, reports http://localhost:4321, and declares the change ready to look at.
You are holding a phone. Localhost on the workstation is not reachable from a phone. The change is not ready to look at, and it was never going to be, because the agent did not know where you test from.
This lesson is short because the fix is short. It is here because it kept recurring until it was written down in three places.
Bind to the network, not to yourself
Every dev script in every app on this machine binds to all interfaces: astro dev --host, next dev --hostname 0.0.0.0, vite --host. The flag lives in the package’s dev script, not in the agent’s memory, so it cannot be forgotten. When an agent starts a server it reports the LAN address, because the constitution says the operator tests on a phone over WiFi and localhost is useless to them.
Every app owns a port, assigned at birth
“Whatever is free” is how you get a port collision a week later, when two dev servers silently fight and one of them serves the wrong app. Each ecosystem on this machine has a range, each app inside it has a fixed port written into its manifest and its dev script, and the scaffolder picks the next free one when the app is created.
Report what the human can use
The last line of “I started the server” should be a URL the person can tap. On this machine that is the LAN address and the app’s fixed port. It is a small thing that removes one round trip from every UI change, and UI changes happen dozens of times a day.
Do not replace a server you did not start
A second agent that starts a server on a port already in use will either fail or, worse, succeed on a random other port and report that instead. The area contract says: bind to the app’s assigned port and report it; do not choose a random port or silently replace an existing server. If the port is busy, say so and stop.
Conventions that live in files beat conventions that live in memory. Bind to the LAN, own a fixed port, report the tappable URL. Then forget about it, which is the point.