How Hardcoded Private IPs Killed Our Production Frontend
A hardcoded private IP buried in the frontend source was silently breaking all external access.
Background
We had an internal ERP system (Vite + React frontend, Express backend) that worked perfectly on the LAN. When we tried to expose it externally, nothing worked.
The Problem
Private IPs were hardcoded throughout the frontend:
const BASE_URL = 'http://192.168.x.x:8520/api';
LAN browsers could reach these IPs. External browsers could not. Even after vite build, these IPs were baked into the bundled JS.
The Fix
- Replaced all hardcoded IPs with relative paths (
/api) - Created
.env.productionwithVITE_API_URL=/api/v1 - Changed nginx from proxying to vite dev server → serving built static files with
try_files - Built and deployed properly
Vite Dev Proxy Trap
server.proxy in vite.config.ts only works during npm run dev. It has zero effect on production builds.
Lessons
- Never hardcode private IPs in frontend code
- Never use Vite dev server in production
server.proxyis dev-only- LAN testing is not real testing