Real-time chess over socket.io. My fork of Reti-Chess.
Built with Node.js | Express | Socket.IO | Pug | chess.js
Games live in memory only: reload or disconnect and the game is gone. There is no database and no accounts — the game link is the only thing gating a game.
npm install
cp .env.example .env
npm run dev # or: npm start
npm run dev loads .env and restarts on change. With BASE_PATH=/chess the
app serves at http://localhost:8181/chess/.
Everything comes from the environment — see .env.example. This replaces the
old ENV switch in public/javascripts/app.js, which hardcoded a host and port
into the client and had to be hand-edited per deploy.
| Var | Default | Notes |
|---|---|---|
PORT |
8181 |
Internal; Apache fronts it in production. |
BASE_PATH |
(empty) | /chess to mount at a subpath. Empty = domain root. |
TRUST_PROXY |
(empty) | 1 behind one reverse proxy. |
LOG_FILE |
logs/games.log |
What GET /logs serves. |
DAW_ORIGIN |
(empty) | Local dev only. See "Shared chrome". |
BASE_PATH drives three things at once: the Express mount, the socket.io path
(${BASE_PATH}/socket.io), and every asset URL in the templates. The client
reads it back from window.$BASE, which views/layout.pug emits. Nothing is
baked in at build time, so the same tree serves / or /chess unchanged.
The app sits behind Apache at davidwindham.com/chess, same shape as /radio:
ProxyPass /chess http://127.0.0.1:8181/chess upgrade=websocket
ProxyPassReverse /chess http://127.0.0.1:8181/chess
The prefix is kept on both sides — BASE_PATH=/chess tells the app to expect
it. upgrade=websocket is what carries socket.io; it needs httpd 2.4.47+ and no
mod_proxy_wstunnel.
Being same-origin with the main site is the point: the client calls io() with
no host, so it follows http/https on its own. The old build dialled
ws://chess.davidawindham.com:8181 explicitly, which a TLS page blocks as mixed
content.
views/layout.pug renders <daw-header> / <daw-footer> and loads
/embed/chrome.js root-relative. In production Apache serves /embed from the
WordPress docroot alongside /chess, so it just works.
Locally, hitting node directly on :8181 has no Apache in front and the chrome
would 404 — set DAW_ORIGIN=http://daw.stu and the app proxies /embed to the
main site. Leave DAW_ORIGIN unset in production. Going through
daw.stu/chess doesn't need it either way.
public/stylesheets/daw.css is the integration layer that pulls the page onto
the site's slate/card palette. It is deliberately separate from style.css so
the migration delta stays isolated — see the comment at the top of that file.
All relative to BASE_PATH.
| Route | Notes |
|---|---|
/ |
Create a game, get a link. |
/about |
|
/play/:token/:time/:increment |
The board. Params are validated; anything malformed is a 404. |
/logs |
Serves games.log. Unauthenticated — see below. |
style.css is edited directly — there is no sass build. A style.scss
used to sit alongside it but had drifted years out of sync (different button,
different palette) with no build step wiring the two, so it was deleted rather
than left as a trap. daw.css holds the daw-integration styles separately./logs is public. Nothing gates it. gameLogger is its only writer and it
records a running game count and nothing else — no addresses, no chat, no
player identifiers. Keep it that way, or put the route behind auth. Operational
logging goes to the console logger precisely so it stays out of that file.TOKEN_RE in server.js pins the shape the /play route will accept._old back into master, still on the old fork.davidwindham.com/chess with the shared site chrome.