Why localhost is a prison and how to escape it
\n\nYou start a server on localhost:3000, 127.0.0.1:5173 or [::1]:8080 — everything works perfectly. Until you ask a colleague or friend to open your project. And then it begins: "Page unavailable", "Connection refused", "ERR_CONNECTION_REFUSED". Sound familiar?
The problem is that localhost (or 127.0.0.1) is a loopback interface. Your server only listens on it. It's like shouting into an empty room: you hear yourself, but no one outside does. In this article, we'll look at how to turn a local server into a public one (or at least accessible on the local network) using TypeScript. No magic, only proven methods.
We'll answer the most common questions from Stack Overflow (where this topic has gathered thousands of views) and provide ready-made solutions for Express, Node.js, and Vite.
\n\n1. The Basics: What Does "Listening on All Interfaces" Mean?
\n\nWhen you write app.listen(3000) in Express, the server by default only listens on localhost. To allow external access, you need to specify 0.0.0.0 (all IPv4 interfaces) or :: (all IPv6).
Here's what it looks like in TypeScript:
\n\nimport express from 'express';\n\nconst app = express();\nconst PORT = 3000;\n\n// Listen on all interfaces\napp.listen(PORT, '0.0.0.0', () => {\n console.log(`Server is running on http://0.0.0.0:${PORT}`);\n console.log(`Available on the local network via your IP`);\n});\n\n\nNow the server is accessible not only on localhost, but also via the local IP of your computer (e.g., 192.168.1.10:3000).
How to find your local IP?
\n- \n
- Windows:
ipconfig→ look for the IPv4 address \n - macOS/Linux:
ifconfigorip addr→ theinet 192.168.x.xline \n
But this is only the first step. Often the problem is deeper — firewall, CORS, or the server still not responding from other devices.
\n\n2. CORS: Why Does the Browser Block Requests?
\n\nEven if you've opened network access, the browser may block requests from another domain. This is the CORS (Cross-Origin Resource Sharing) policy. The solution is to configure headers on the server.
\n\nInstall the cors package for Express:
npm install cors\nnpm install @types/cors --save-dev\n\n\nInclude it in your TypeScript server:
\n\nimport express from 'express';\nimport cors from 'cors';\n\nconst app = express();\n\n// Allow all origins (for development)\napp.use(cors({\n origin: '*',\n methods: ['GET', 'POST', 'PUT', 'DELETE'],\n allowedHeaders: ['Content-Type', 'Authorization']\n}));\n\napp.listen(3000, '0.0.0.0', () => {\n console.log('CORS enabled, server accessible from outside');\n});\n\n\nImportant: In production, do not use origin: '*' — specify specific domains.
3. Firewall: The Invisible Blocker
\n\nEven if the server listens on 0.0.0.0, your firewall may block incoming connections. This is a common reason why external access doesn't work.
How to open a port (using Windows as an example):
\n- \n
- Open "Windows Defender Firewall" \n
- Click "Advanced settings" \n
- Create an inbound rule \n
- Specify the port (e.g., 3000) and protocol (TCP) \n
- Allow the connection \n
On macOS/Linux, use ufw or iptables:
# Allow port 3000 via ufw\nsudo ufw allow 3000/tcp\n\n\n