3.4 KiB
One-Port WebSocket Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Serve Express HTTP endpoints, static frontend, and WebSocket traffic on one WEBSERVER_PORT using WebSocket path /ws.
Architecture: src/webserver.ts should create one http.Server from the Express app, attach WebSocketServer to that same server with path: "/ws", and remove port + 1. public/index.html should connect to ${location.protocol === "https:" ? "wss" : "ws"}://${location.host}/ws so dev, production, and reverse proxy setups use the same host and port.
Tech Stack: TypeScript, Express, Node HTTP server, ws, Bun scripts, Biome, TypeScript compiler.
File Structure
- Modify
src/webserver.ts: change WebSocket server construction and logs from separate port to shared HTTP server path/ws. - Modify
public/index.html: change browser WebSocket URL from hardcoded:3001to same-origin/ws. - No new files required.
Task 1: Attach WebSocket to Existing HTTP Server
Files:
-
Modify:
src/webserver.ts -
Step 1: Update WebSocket server creation
Replace this code in src/webserver.ts:
const wsPort = port + 1;
const wss = new WebSocketServer({ port: wsPort, host: "0.0.0.0" });
wsLogger.info({ wsPort }, "WebSocket server listening");
With:
const wsPath = "/ws";
const wss = new WebSocketServer({ server, path: wsPath });
wsLogger.info({ port, wsPath }, "WebSocket server listening");
- Step 2: Update connection log
Replace this code in src/webserver.ts:
wsLogger.info({ wsPort }, "New WebSocket connection");
With:
wsLogger.info({ port, wsPath }, "New WebSocket connection");
- Step 3: Run typecheck
Run:
bun run typecheck
Expected: command exits 0.
Task 2: Update Browser WebSocket URL
Files:
-
Modify:
public/index.html -
Step 1: Replace hardcoded WebSocket port
Replace this code in public/index.html:
socket = new WebSocket(`ws://${window.location.hostname}:3001`);
With:
const wsProtocol = window.location.protocol === "https:" ? "wss:" : "ws:";
socket = new WebSocket(`${wsProtocol}//${window.location.host}/ws`);
- Step 2: Run lint and build
Run:
bun run lint && bun run build
Expected: both commands exit 0.
Task 3: Verify One-Port Behavior
Files:
-
Verify:
src/webserver.ts -
Verify:
public/index.html -
Step 1: Start dev server
Run:
bun run dev
Expected logs include Express web interface on configured port and WebSocket server listening with { port: 3000, wsPath: "/ws" }.
- Step 2: Browser smoke test
Open:
http://localhost:3000
Expected: page loads and browser WebSocket connects to:
ws://localhost:3000/ws
- Step 3: Endpoint smoke test
Run:
curl http://localhost:3000/health
curl http://localhost:3000/metrics
Expected: /health returns JSON and /metrics returns Prometheus text.
Self-Review
- Spec coverage: Covers one-port HTTP/WebSocket server,
/wspath, frontend URL update, and verification. - Placeholder scan: No TBD/TODO placeholders.
- Type consistency: Uses
wsPathin both server creation and logs; frontend connects to/ws.