How to open your localhost dev server on your phone
Your app runs at http://localhost:5173 on your Mac, and you want to see it on your phone. Typing localhost on the phone opens nothing, and your Mac's IP address doesn't work either. The fix is usually one flag. Here's why, and the flag for each common framework.
Why it doesn't work
localhost always means "this device." On your phone, it's the phone. So you need your Mac's address on the network instead. You can find it with:
ipconfig getifaddr en0
That gives something like 192.168.1.23, so on the phone you'd open http://192.168.1.23:5173. Usually that fails too, because most dev servers only listen on 127.0.0.1, the Mac's private loopback address. Connections from other devices never reach them. That's a safe default: a half-finished app with debug tools shouldn't be reachable by everyone on the café Wi-Fi.
The fix is to tell the dev server to listen on all network interfaces, written 0.0.0.0, while you're on a network you trust.
The flag for your framework
| Tool | Command |
|---|---|
| Vite | npm run dev -- --host (or server.host: true in vite.config) |
| Next.js | npx next dev -H 0.0.0.0 |
| Astro | npm run dev -- --host |
| webpack-dev-server | --host 0.0.0.0 |
| Rails | bin/rails server -b 0.0.0.0 |
| Django | python manage.py runserver 0.0.0.0:8000, and add your Mac's IP to ALLOWED_HOSTS |
| Flask | flask run --host=0.0.0.0 |
| Static files | python3 -m http.server 8000 (listens on all interfaces already) |
Vite and Astro helpfully print a Network address when you pass --host. Open that on your phone.
A few frameworks also check which address a request came in on. If the page loads but assets or hot reload fail, look for a setting like Django's ALLOWED_HOSTS, webpack's allowedHosts or, in recent Next.js versions, allowedDevOrigins, and add your Mac's IP address there.
Still not loading? Check these
- Same network. The phone must be on the same Wi-Fi as the Mac, not on cellular and not on a guest network. Guest networks often block devices from seeing each other.
- The Mac's firewall. If it's on (System Settings → Network → Firewall), macOS asks whether to allow incoming connections the first time a program listens on the network. If you clicked Deny, change it in the firewall's options.
- Company networks and VPNs. Some VPN clients block local network traffic while connected. Try with the VPN off.
- iPhone's Local Network permission applies to apps, not Safari, so Safari is the simplest way to test.
Features that need HTTPS
Browsers treat http://localhost as secure, but http://192.168.1.23 isn't. So on your phone, features that require a secure context stop working: the camera and microphone, service workers, the clipboard API and others. Options:
- A local certificate.
mkcertcreates a certificate your devices trust. You install its root certificate on the phone once, then serve over HTTPS. Vite has@vitejs/plugin-basic-sslfor a quick self-signed setup; the phone will warn once. - A tunnel.
cloudflared tunnel --url http://localhost:5173or ngrok gives you a temporary publichttps://address. It works from any network, including cellular. It's also public, so don't leave it running on an app with real data.
Testing from your phone when you're not at your desk
Once the page is on your phone, you'll usually want to change something: restart the server, read an error in its log, rerun the build. Normally that means walking back to the Mac.
With PandaSend Terminal, the dev server can run in a PandaSend session on your Mac, and you open that same terminal on your phone to read the log, press Ctrl-C and restart it, or run a command, from the couch or on cellular. It's the running session itself, end-to-end encrypted, not a copy. See how it compares with SSH and tmux.