Mall World (Game)
A browser-based 3D liminal hangout — ski the marble, dodge the nightmare, talk to the fortune teller.
Mall World is a multiplayer 3D game you play in a browser tab: a dream-logic shopping mall you wander with strangers, with momentum skiing, mid-air jetpacks, NPCs who talk back, and a nightmare that periodically comes for the whole server. TypeScript end to end — React Three Fiber and Rapier on the client, Fastify + Colyseus + SQLite on the server, with an authoritative 20 Hz tick that owns every piece of game truth. Passkey auth, guests spawn instantly. This exhibit is the USWest instance; the engine is built to deploy as independent federated servers.
- TypeScript
- React 19
- React Three Fiber
- Three.js
- Rapier
- Colyseus
- Fastify
- SQLite
- WebAuthn
- Vite
- pnpm
Mall World is a 3D multiplayer hangout that runs in a browser tab. You spawn as a guest into a dream-logic shopping mall — neon storefronts, a fountain full of galaxy, a food court that goes on further than it should — and wander it alongside whoever else is currently awake. It is a game about drifting somewhere pleasant with strangers, occasionally interrupted by something much worse.
How it plays
- Movement is the whole toy. WASD and jump are the floor; the ceiling is skiing — hold space in the air and friction and damping go to zero, so momentum is sacred and the marble becomes a downhill course. Right-mouse runs on the ground and fires a jetpack in the air, with thrust tuned so it never claws back speed you already earned.
- NPCs you can actually talk to — Officer Wick, Madame Reverie, PORTER, ZOLTAR the fortune teller, a vending machine with opinions, and a mall cat.
- Nightmares. The server periodically turns the mall against everyone in it — postprocessing shifts, monsters spawn, and the pleasant part is over for a while.
- Abilities and destructibles — a shield and a charge-and-release "Dream Buster", both drawing from a shared Lucid meter that doubles as ammo for everything. World objects can be flagged breakable and respawn on a timer.
How it's built
One language end to end. The client is React 19 with React Three Fiber, drei and Rapier (WASM physics) on Three.js, bundled by Vite. The server is a single Node process running Fastify for HTTP and Colyseus for the websocket layer, backed by better-sqlite3 — one file, forward-only migrations, no external services.
The architectural rule that keeps it honest: the server owns all game truth. Positions, meters, coins, items, quest flags, dialogue, projectiles, monsters and damage are all resolved on a 20 Hz authoritative tick; the client is a renderer that predicts locally for feel and sends small intent messages. Anything both sides need — Colyseus schemas, the Zod world format, the item catalog, HP curves — lives in a shared workspace package that is the single arbiter when the two disagree. State deltas are held under 4 KB per tick at sixteen players.
Worlds are data, not code: one Zod-validated JSON document carries the layout (buildings, objects, lights, NPCs, spawn points, teleports) and the gameplay knobs (movement tuning, meters, nightmare cadence), so a designer retunes the game in the in-browser editor without a deploy. Auth is passkey-first via SimpleWebAuthn, but no account is required to play — guests spawn as a procedurally-generated glowing blob, and user-imported VRM avatars are validated and size-clamped on the way in.
Where it's going
The engine is deliberately content-free where it can be, because the roadmap is federation: one codebase deployed as sovereign servers, each with its own database, moderation and economy, plus "Dimensions" — fully isolated game variants inside a single server. USWest, the instance shown here, is the first of those.
Straight from the source
The project's own README.
Rendered in place — every link, image, and code block carried over from the repo. The page below is what a contributor would see opening the project for the first time.
Mall World
A browser-based 3D liminal hangout game. Customizable avatars, real-time chat, dream-logic geometry, periodic nightmares, federated servers.
This is one server instance — USWest ("Alpha Mall World"),
deployed at https://uswest.mallworld.org/.
For humans
Open docs/quick-start.md.
For agents
Open docs/quick-start.md, then docs/AGENT-PROTOCOL.md, then start
on docs/init/STATUS.md's first unchecked item.
Quick commands
just # list everything
just dev # client + server in watch mode
just deploy # build + restart systemd
just logs # tail journal
Repo shape
apps/
client/ # Vite + React + R3F + Rapier
server/ # Fastify + Colyseus + better-sqlite3
packages/
shared/ # Colyseus schemas, world types, validators
starter-assets/ # Seed GLBs, default avatar, sample world
scripts/ # Seed + maintenance scripts
docs/ # All design + agent docs
data/ # Runtime data (gitignored)
db.sqlite
assets/
justfile # Single source of truth for ops
Tech
TypeScript everywhere. React Three Fiber for 3D. Colyseus for
multiplayer. SimpleWebAuthn for passkeys. better-sqlite3 for state.
See docs/TECH-STACK.md for justifications.
License
Private — saintpetejackboy/mallworld-game.
Build something like this
Want a tool like this for your shop?
We've shipped this kind of thing before. Twenty-minute intro call, no slides.