Vite HMR Through a Tunnel
Start Vite + tunnel
# Terminal 1
npm run dev
# Terminal 2
npx localtolink --port 5173
Vite configuration
Add to vite.config.js (or .ts):
import { defineConfig } from "vite";
export default defineConfig({
server: {
allowedHosts: [".localtolink.com"],
hmr: {
clientPort: 443,
protocol: "wss",
},
},
});
What each setting does
| Setting | Purpose |
|---------|---------|
| allowedHosts: [".localtolink.com"] | Allows the dev server to respond to tunnel hostnames |
| hmr.clientPort: 443 | HMR WebSocket connects via HTTPS port (tunnel terminates TLS) |
| hmr.protocol: "wss" | Secure WebSocket through the tunnel |
Restart Vite after saving the config.
Verify HMR
- Open the tunnel URL in a browser (click through the interstitial if shown)
- Edit a component file
- Confirm hot reload without full page refresh
Phone testing
Scan the terminal QR code to test HMR on a physical device:
npx localtolink --port 5173
# QR code prints automatically; use --no-qr to hide
See Test Localhost on Your Phone.
Troubleshooting
| Issue | Fix |
|-------|-----|
| HMR not connecting | Verify clientPort: 443 and protocol: "wss" |
| Blocked host | Add .localtolink.com to allowedHosts |
| Full page reload only | Check browser console for WebSocket errors |
| Session expired | Restart tunnel (2-hour limit) |
WebSocket support
LocalToLink forwards WebSocket upgrades bidirectionally — required for Vite HMR. This is supported in v1.0 with no extra configuration on the tunnel side.
Try it now
Start a tunnel from your project directory — no account required.
$ npx localtolink