Generate the client config instead of listing it by hand

The browser gets its constants from a /config.js route that re-declared each
export by hand, so a constant added to config.js and imported by the frontend
linked against nothing. WASH_FRAME_SCALE, added with the colour wash, did
exactly that: motion.js failed to link, player.js never ran, and the start gate
sat on its hardcoded "Loading queue..." forever.

Serialise every export except the server-only PORT, so the mirror cannot drift
from the source again.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Tg15tLAuT6NrCE1ZxKVgDB
This commit is contained in:
simon
2026-08-09 23:43:21 +02:00
co-authored by Claude Opus 5
parent f55298ff4f
commit ade77b4c38
+12 -44
View File
@@ -7,29 +7,8 @@ import { fileURLToPath } from 'node:url';
import express from 'express';
import { WebSocketServer } from 'ws';
import {
PORT,
OVERLAP_SECONDS,
HARD_CUT_SECONDS,
FRAME_SCALE,
BOUNCE_SPEED,
CORNER_INTERVAL_SECONDS,
CORNER_MARGIN,
DRAG_FRAME_SCALE,
DRAG_MIN_SCALE,
DRAG_MAX_SCALE,
TRAIL_SPEED,
TRAIL_TURN_RATE,
TRAIL_SPACING,
TRAIL_LENGTH,
TRAIL_FADE_SECONDS,
WASH_CYCLE_SECONDS,
WASH_SPREAD,
WASH_STRENGTH,
BACKGROUNDS,
ANIMATIONS,
AUTO_ANIMATION,
} from '../config.js';
import * as config from '../config.js';
import { PORT, BACKGROUNDS } from '../config.js';
import { parseVideoId, fetchTitle } from './youtube.js';
import * as store from './state.js';
@@ -48,28 +27,17 @@ app.use('/assets', express.static(join(ROOT, 'assets'), { maxAge: '1h' }));
app.use(express.static(join(ROOT, 'public')));
// Client-side mirror of the shared config, so the constants live in one place.
// Generated from the module's exports rather than listed by hand: a constant
// added to config.js and imported by the frontend used to break the whole
// module graph — and with it the player — until this list was updated too.
// PORT is server-only; everything else travels.
const CLIENT_CONFIG = Object.entries(config).filter(([name]) => name !== 'PORT');
app.get('/config.js', (_req, res) => {
res.type('application/javascript').send(
`export const OVERLAP_SECONDS = ${OVERLAP_SECONDS};\n` +
`export const HARD_CUT_SECONDS = ${HARD_CUT_SECONDS};\n` +
`export const FRAME_SCALE = ${FRAME_SCALE};\n` +
`export const BOUNCE_SPEED = ${BOUNCE_SPEED};\n` +
`export const CORNER_INTERVAL_SECONDS = ${CORNER_INTERVAL_SECONDS};\n` +
`export const CORNER_MARGIN = ${CORNER_MARGIN};\n` +
`export const DRAG_FRAME_SCALE = ${DRAG_FRAME_SCALE};\n` +
`export const DRAG_MIN_SCALE = ${DRAG_MIN_SCALE};\n` +
`export const DRAG_MAX_SCALE = ${DRAG_MAX_SCALE};\n` +
`export const TRAIL_SPEED = ${TRAIL_SPEED};\n` +
`export const TRAIL_TURN_RATE = ${TRAIL_TURN_RATE};\n` +
`export const TRAIL_SPACING = ${TRAIL_SPACING};\n` +
`export const TRAIL_LENGTH = ${TRAIL_LENGTH};\n` +
`export const TRAIL_FADE_SECONDS = ${TRAIL_FADE_SECONDS};\n` +
`export const WASH_CYCLE_SECONDS = ${WASH_CYCLE_SECONDS};\n` +
`export const WASH_SPREAD = ${WASH_SPREAD};\n` +
`export const WASH_STRENGTH = ${WASH_STRENGTH};\n` +
`export const BACKGROUNDS = ${JSON.stringify(BACKGROUNDS)};\n` +
`export const ANIMATIONS = ${JSON.stringify(ANIMATIONS)};\n` +
`export const AUTO_ANIMATION = ${JSON.stringify(AUTO_ANIMATION)};\n`,
res
.type('application/javascript')
.send(
CLIENT_CONFIG.map(([name, value]) => `export const ${name} = ${JSON.stringify(value)};\n`).join(''),
);
});