Files
dc-recorder/docs/superpowers/plans/2026-05-13-one-port-websocket.md

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 :3001 to 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, /ws path, frontend URL update, and verification.
  • Placeholder scan: No TBD/TODO placeholders.
  • Type consistency: Uses wsPath in both server creation and logs; frontend connects to /ws.