Two devices on the same WiFi could fail to discover each other on Vercel because
/api/network grouped peers by their full public IP. That holds for IPv4 +
NAT (one shared address per LAN) but breaks under IPv6, where every device gets
its own global address out of the LAN's shared /64 — so the hashes differed and
peers landed in separate Realtime rooms.
Fixed
app/api/network/route.tsnow reduces the client IP to a "same network" key before hashing: full address for IPv4, the /64 prefix for IPv6 (expands::zero-compression first), and the embedded IPv4 for IPv4-mapped IPv6. Also strips brackets / a trailing:portfrom IPv6 literals. Raw IP still never leaves the server.tests/network-route.test.tsgained IPv6 /64 grouping, IPv4-mapped, and bracket/port coverage.
Note: discovery + signaling still require Supabase env vars (NEXT_PUBLIC_*),
which are inlined at build time — set them in Vercel and redeploy, or the
feature stays off. Cross-network/strict-NAT links still need a TURN server
(NEXT_PUBLIC_TURN_*).