Skip to content

Contributing ​

Thank you for helping. Issues labelled good first issue and help wanted are good places to start. For the art, see #2 and #4.

Set up ​

Node 24 and pnpm 10 (corepack enable), plus Docker for the database and storage.

bash
pnpm install
pnpm dev                 # the client, http://localhost:5173 (single-player)
pnpm db:up               # Postgres (port 5433) and S3 storage (8333) in Docker
DATABASE_URL=postgres://mall:mall@localhost:5433/mall \
S3_ENDPOINT=http://localhost:8333 S3_BUCKET=mall S3_ACCESS_KEY_ID=mall S3_SECRET_ACCESS_KEY=mall-secret \
HOST_SECRET=letmein pnpm dev:server   # multiplayer, /api and /admin, port 8787

Open a second browser window to see yourself walk around. ?debug shows an fps and draw-call overlay and the navgrid.

Layout ​

FolderWhat's there
client/The browser app: three.js world, Preact UI (src/ui), admin page (src/admin, admin/index.html)
server/Node WebSocket server, content API, uploads, Postgres migrations
shared/Code both sides use: protocol, config schema, meta schema, navgrid, avatars list
tools/Greybox generator, navgrid baker, asset pipeline, Blender build, bots, perf and a11y gates
assets-src/Source art (CC0 kits, Higgsfield models, audio) with licences
docs/This site, the ADRs and the task list

Read Architecture first. The decisions behind it are in the ADRs.

Checks (all run in CI) ​

CommandWhat it checks
pnpm lintBiome: format and lint (pnpm format fixes most things)
pnpm typecheckTypeScript, strict
pnpm testVitest: client, server, shared, tools. Database and storage tests need TEST_DATABASE_URL and TEST_S3_ENDPOINT, and skip without them.
pnpm build && pnpm sizeBundle size budget (initial JS ≤ 220 KB gzipped)
pnpm perfLoad and runtime budgets in Chromium on throttled 4G (--gpu to enforce frame time)
pnpm a11yaxe-core on every main screen, plus a keyboard-only flow
pnpm screenshotsPhone layouts (iPhone 13 portrait and landscape, Pixel 7) into screenshots/

Asset commands: pnpm greybox (layout, collision, meta, navgrid), pnpm assets (avatar, props and audio packs), pnpm mall (the Blender build, which needs Blender). Every shipped asset has a size budget in tools/test/budgets.test.ts.

Conventions ​

  • Performance is a feature. No allocations in the render loop, one draw call per thing where possible, and lazy-load anything not needed for the first frame. The budgets are in performance.md.
  • Code reads simply. Short files and plain functions. Comments say why. Server and shared code run as TypeScript straight in Node, so they use erasable syntax only (no enums or namespaces) and .ts import extensions.
  • The UI never imports three.js, and the game never touches the DOM except the canvas: they talk through signals (client/src/state.ts) and commands (client/src/commands.ts).
  • Accessible and bilingual. Every control has a label, and every string goes through t() with both en and my entries.
  • Commits: one task per commit, with an imperative subject (feat: …, fix(ui): …, perf: …) and the task ID or issue in the subject.

MIT licensed code. Assets CC BY 4.0 unless noted.