Skip to content

Commit 363ca7c

Browse files
davindicodeclaude
andcommitted
Replace per-port cloudflared tunnels with /proxy/:port reverse proxy
Route all localhost previews through the existing Express reverse proxy instead of spawning separate cloudflared quick tunnels per port. This avoids Cloudflare rate-limiting on ephemeral DNS registrations. - BrowserPage: vertical session list with proxy reachability checks, copy/go/delete per row, inline add-port input - browserStore: remove socket-based tunnel cleanup - socket-handlers: remove all tunnel socket handlers - tunnel.ts: delete per-port tunnel functions, simplify stopAllTunnels - InputBox: code tab vendor selector as portal dropup with triangle toggle - README: document proxy architecture and dev server notes Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent aad90db commit 363ca7c

6 files changed

Lines changed: 254 additions & 405 deletions

File tree

README.md

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@
7676

7777
### Layout & Access
7878
- **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
8181

8282
## Quick Start
8383

@@ -146,12 +146,24 @@ Express (port 7777)
146146
├── React Router v7 — UI (SSR shell + client-side app)
147147
├── Socket.IO — real-time terminal I/O via node-pty
148148
├── 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)
151151
```
152152

153153
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.
154154

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+
155167
## Tech Stack
156168

157169
React Router v7, Express, Socket.IO, node-pty, xterm.js, Monaco Editor, Zustand, Tailwind CSS v4, TypeScript

0 commit comments

Comments
 (0)