Files
segnapunti/CLAUDE.md
T

3.6 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Purpose

Segnapunti Anto is a real-time volleyball scoreboard PWA. An Express/WebSocket server hosts the game state; two separate web interfaces — a display (public scoreboard) and a controller (operator panel) — stay in sync via WebSocket. A terminal CLI (cli.js) provides an alternative controller interface.

Commands

npm run dev          # Vite dev server — display: :5173, controller: :5173/controller.html (proxied on :3001)
npm run serve        # Build + run production — display: :3000, controller: :3001
npm run cli          # Terminal controller (connects to production :3000)
npm run cli:dev      # Terminal controller (connects to dev :5173)

npm run test         # Vitest watch mode
npm run test:all     # All Vitest suites once (unit, integration, component, stress)
npm run test:unit    # Unit + integration only
npm run test:component  # Vue component tests
npm run test:stress  # Load tests (50+ concurrent clients)
npm run test:e2e     # Playwright E2E (requires servers to be running via npm run serve)
npm run test:e2e:ui  # Playwright with interactive UI

Architecture

Controller (Vue)  ──WebSocket──┐
Display (Vue)     ──WebSocket──┤── websocket-handler.js ── gameState.js
CLI (Node)        ──WebSocket──┘

All game logic lives in src/gameState.js as three pure functions:

  • createInitialState() — returns the initial state
  • applyAction(state, action) — immutable reducer (deep-clones via JSON.parse/stringify)
  • checkVittoria(state) — volleyball win conditions (25-point sets with 2-point margin, 15-point final set)

src/websocket-handler.js receives actions, validates that the sender is a registered controller (not just a display), calls applyAction, then broadcasts the new state to all clients.

Two production HTTP servers are started by server.js (Express): port 3000 serves dist/index.html (display), port 3001 serves dist/controller.html (controller). Both share a single WebSocket endpoint at /ws.

In development, vite-plugin-websocket.js is a custom Vite plugin that embeds the WebSocket server inside the Vite dev server and proxies port 3001 traffic back to Vite.

Key Design Constraints

  • All game rules on the server — clients are pure UI; the server is the source of truth.
  • Role-based WebSocket — clients register as display or controller; only controllers may send actions.
  • Immutable stateapplyAction never mutates; always returns a new state object.
  • Single-controller intent — the design targets one active controller and one display; no conflict resolution exists for simultaneous controllers.

Test Layout

Suite Path Runner
Unit tests/unit/ Vitest + Node
Integration tests/integration/ Vitest + Node
Component tests/component/ Vitest + Happy-DOM
Stress tests/stress/ Vitest + Node
E2E tests/e2e/ Playwright (Chromium, Firefox, Mobile Chrome)

E2E tests run serially (workers: 1) to avoid WebSocket state races. Run npm run serve before npm run test:e2e.

Simplification Goals (Current Work)

The intended architecture is: one host acts as both WebSocket server and display; one connected device acts as controller. Complexity reduction should be evaluated against this constraint — anything that supports multi-controller scenarios, complex client topologies, or unneeded abstractions is a candidate for removal.