|
76 | 76 |
|
77 | 77 | ### Layout & Access |
78 | 78 | - **Responsive** — 3-column resizable panels on desktop/landscape, single-panel with bottom tab bar on mobile/portrait (orientation-aware breakpoint) |
79 | | -- **Localhost Browser** — reverse proxy to preview any localhost port, multi-tab with console output |
80 | | -- **Cloudflare Tunnel** — one command (`./start.sh`) to build, start, and expose via public URL |
| 79 | +- **Localhost Browser** — preview any localhost port via `/proxy/:port` reverse proxy (single tunnel, no per-port cloudflared processes), multi-tab with reachability checks |
| 80 | +- **Cloudflare Tunnel** — one command (`./start.sh`) to build, start, and expose via public URL; all localhost previews route through the same tunnel |
81 | 81 |
|
82 | 82 | ## Quick Start |
83 | 83 |
|
@@ -146,12 +146,24 @@ Express (port 7777) |
146 | 146 | ├── React Router v7 — UI (SSR shell + client-side app) |
147 | 147 | ├── Socket.IO — real-time terminal I/O via node-pty |
148 | 148 | ├── REST API — file operations (list, read, write, rename, delete, upload, download, mkdir) |
149 | | -├── Reverse Proxy — /proxy/:port/* forwards to localhost services |
150 | | -└── Cloudflare Tunnel — optional public URL via cloudflared |
| 149 | +├── Reverse Proxy — /proxy/:port/* forwards HTTP + WebSocket to localhost services |
| 150 | +└── Cloudflare Tunnel — single optional tunnel via cloudflared (all traffic, including localhost previews) |
151 | 151 | ``` |
152 | 152 |
|
153 | 153 | All three panels (Files, Terminal, Browser) are always mounted in the DOM with CSS visibility toggling — preserving terminal state, WebSocket connections, and iframe content across navigation. |
154 | 154 |
|
| 155 | +### Localhost Preview |
| 156 | + |
| 157 | +The Browser tab previews any localhost port through the Express reverse proxy — no extra tunnels or processes are spawned. When you enter a port, the UI checks reachability via `/proxy/:port/` and gives you a link to open in a new tab. |
| 158 | + |
| 159 | +The proxy handles: |
| 160 | +- **Path rewriting** — strips the `/proxy/:port` prefix before forwarding to `127.0.0.1:<port>` |
| 161 | +- **WebSocket upgrades** — WS connections on `/proxy/:port/...` are forwarded (supports Vite HMR, webpack-dev-server, etc.) |
| 162 | +- **Header stripping** — removes `X-Frame-Options` and CSP headers so content can embed |
| 163 | +- **Asset path rewriting** — rewrites absolute paths in HTML, CSS, JS (src, href, url(), ES imports) to include the `/proxy/:port` prefix |
| 164 | + |
| 165 | +**Dev server notes:** Most dev servers (Vite, webpack, Next.js) work out of the box since both HTTP and WebSocket traffic are proxied. However, dev servers that hardcode their WebSocket URL to `ws://localhost:<port>` in client-side code (bypassing the proxy path) will fail over the tunnel — the HMR connection won't reach the VPS. Vite works because its HMR client connects relative to the page origin. If a dev server's HMR breaks, configure it to use a relative or custom WebSocket path. |
| 166 | + |
155 | 167 | ## Tech Stack |
156 | 168 |
|
157 | 169 | React Router v7, Express, Socket.IO, node-pty, xterm.js, Monaco Editor, Zustand, Tailwind CSS v4, TypeScript |
|
0 commit comments