Skip to content

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

bash
git clone https://github.com/zebadrabbit/Anomalist.git
cd Anomalist
npm install
npm run dev

npm 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 site

packages/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

bash
npm run typecheck   # every workspace
npm run build       # every workspace
npm test            # server test suite
npm run docs:build  # this site

CI 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:

bash
cd apps/server
node --import tsx --test test/media.test.ts        # a single file
node --import tsx --test test/*.test.ts            # everything

test/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

bash
docker compose up -d --build

docker compose pull does nothing here — the image is built from source rather than pulled, so --build is what actually updates it.

Documentation

bash
npm run docs:dev

The 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.

Next steps

Released under the MIT License.