Setup
Requirements
- Node 22 or newer. The repo pins it in
.nvmrc, and CI and the Docker image both use it. - Docker, if you want to run the container rather than the dev servers.
Getting started
git clone https://github.com/zebadrabbit/Anomalist.git
cd Anomalist
npm install
npm run devnpm run dev starts every workspace: the server on 3001, the dashboard and the overlay on their Vite dev servers.
Create apps/server/.env from apps/server/.env.example if you want to set OWNER_TOKEN or point the database somewhere specific.
Layout
apps/
server/ Express + socket.io + SQLite
dashboard/ SvelteKit control panel
overlay/ SvelteKit page OBS loads
packages/
types/ Shared types and the socket event names
widget-sdk/ Public API for community widgets
docs/ This sitepackages/types must build before anything that imports it, which is why the root build and test scripts have a prebuild/pretest step that builds it first. Its dist is gitignored, so a clean checkout has to build it before tests will run.
Checks
npm run typecheck # every workspace
npm run build # every workspace
npm test # server test suite
npm run docs:build # this siteCI runs exactly that sequence, in that order, on Node 22. Running it locally before opening a PR is the fastest way to avoid a red run.
Type checking covers src and test in the server workspace — the build uses a separate tsconfig.build.json that emits only from src.
Tests
The server suite uses node:test with tsx, no framework:
cd apps/server
node --import tsx --test test/media.test.ts # a single file
node --import tsx --test test/*.test.ts # everythingtest/support.ts boots the real server on an ephemeral port against a temporary database and media directory, so tests exercise the actual routes and sockets rather than mocks.
Each file gets its own process, which matters for anything that reads environment variables at import time — that is how the TRUST_PROXY tests set up opposite configurations without interfering.
Writing one
Prove the failure first. Every fix in the test suite was watched failing before it was made to pass, and more than one of them turned out to be testing the wrong thing until that step forced the issue.
Docker
docker compose up -d --builddocker compose pull does nothing here — the image is built from source rather than pulled, so --build is what actually updates it.
Documentation
npm run docs:devThe site is VitePress, built from docs/ and deployed to GitHub Pages on every push to main. Screenshots in docs/public/screenshots are validated in CI, so a placeholder or truncated file fails the build rather than shipping.
Brand assets are generated by scripts/generate-brand-assets.mjs rather than committed by hand — re-run it if the mark changes.
Pull requests
See CONTRIBUTING.md for the project's expectations. In short: small, single-purpose, with tests and docs updated when behaviour changes.
