A walking-skeleton proof of concept for a Habbo-style isometric social game, rebuilt from scratch on SpacetimeDB. The target demo: two browser tabs against a local SpacetimeDB node, each rendering an avatar in a shared room — click-to-walk with server-authoritative pathfinding, furni placement from a small inventory, and chat (in-world bubbles + DOM log). Every action in tab A appears live in tab B.
Status: early PoC under active development. See BACKLOG.md for scope, epics, and current progress.
┌─────────────────────────────┐ WebSocket ┌──────────────────────┐
│ client/ (Angular 22) │ ◀────────────▶ │ server/ (Rust) │
│ zoneless · render worker │ │ SpacetimeDB module │
│ coalesced bridge protocol │ │ habtime-poc │
└─────────────────────────────┘ └──────────────────────┘
| Directory | What it is |
|---|---|
server/ |
Rust SpacetimeDB module (habtime-poc): tables (account, session, config, …) and reducers (connection lifecycle, set_name, scheduled room tick) |
client/ |
Angular 22 zoneless app. A dedicated render worker owns the SpacetimeDB connection and the modified Nitro/PixiJS v8 room scene; the main thread talks to it over a coalescing message bridge (client/src/bridge/) |
client/src/module_bindings/ |
TypeScript bindings generated from the server module by spacetime generate |
nitro-renderer/ |
Workspace-local modified Nitro renderer packages used by the render worker for room planes, depth sorting, avatars, and room updates |
docs/research/, docs/modules/ |
Research notes on SpacetimeDB; developer-reference docs for the original Habbo stack used as source material |
MODULES.md, RENDERER.md, UI.md, CHAT.md, TESTING.md |
Design decision records: reference-stack module inventory, renderer, UI, chat, and testing strategies |
- Server: Rust, SpacetimeDB SDK 2.x,
pathfindingcrate (A*) - Client: Angular 22 (zoneless, standalone components), modified Nitro renderer with PixiJS v8, Vitest + jsdom, SCSS, Bun workspaces
- Tooling: Bun, ESLint (typescript-eslint), Prettier, SpacetimeDB CLI
A traditional Habbo Retro pairs the Arcturus-Community Java emulator with the Nitro web client (nitro-renderer engine + nitro-react UI). MODULES.md documents that stack in depth. habtime uses a modified, workspace-local Nitro renderer for the room and avatar pipeline, while replacing the emulator and nitro-react application with SpacetimeDB and Angular:
| Classic retro (Arcturus + Nitro) | habtime | |
|---|---|---|
| Components | Three codebases: Java emulator, renderer engine, React UI | Rust SpacetimeDB module, Angular app, and modified Nitro renderer workspace packages |
| Server | Java 8 emulator backed by MySQL (HikariCP); Netty TCP socket server plus a separate JSON RCON admin port | A single SpacetimeDB module — game state lives in tables, logic runs as transactional reducers, scheduled ticks are first-class |
| Protocol | Hand-written EvaWire packets; every message exists as paired classes kept in sync 1:1 across all three codebases (~350 inbound handlers, ~465 outbound composers) | Typed bindings auto-generated from the server schema (spacetime generate); clients subscribe to queries and receive row deltas over one WebSocket |
| Client engine | nitro-renderer library consumed by nitro-react through an events/API bridge; PixiJS ~6.5 on the main thread |
Modified nitro-renderer packages run in the render worker with the SpacetimeDB connection and PixiJS v8 scene graph; the main-thread UI talks to it over a small coalescing message bridge |
| Login | Diffie-Hellman/RSA key exchange with RC4 session ciphers against emulator accounts | Anonymous SpacetimeDB identity with a persisted private token; real auth (BetterAuth) deliberately deferred past the PoC |
| Assets | SWF-derived XML/spritesheets from the original hotel | Local room/furni art plus build-time Habbo imager frames for one fixed figure |
The point is not that one approach is better across the board: the classic stack encodes decades of Habbo semantics we intentionally mine for feature design, while SpacetimeDB removes whole subsystems we would otherwise have to build (packet registry, ORM/persistence, RCON, tick scheduling glue).
- Bun
- Rust toolchain (stable,
cargoon PATH) - SpacetimeDB CLI (
spacetime)
# install workspace dependencies
bun install
# terminal 1 — start a local SpacetimeDB node
bun run node:start
# build the server module
bun run server:build
# regenerate TypeScript bindings after changing the server schema
bun run bindings:gen
# serve the Angular app
bun run --cwd client start # http://localhost:4200The database name is habtime-poc. Publishing and dev-watch flows are being wired up as backlog stories land; for now use the spacetime CLI directly (e.g. spacetime publish) against your local node started above.
| Script | What it does |
|---|---|
bun run node:start |
Starts a local SpacetimeDB node |
bun run server:build |
Builds the Rust module (spacetime build) |
bun run bindings:gen |
Generates TS module bindings into client/src/module_bindings |
bun run test:server |
Runs Rust unit tests (cargo test) |
bun run test:client |
Runs Angular/Vitest unit tests (no watch) |
bun run check |
Server tests + client tests |
bun run lint |
ESLint across the workspace |
BACKLOG.md— PoC scope, goals/non-goals, epics and storiesRENDERER.md— renderer foundation decisions (PixiJS v8 in a worker)UI.md— UI architecture and main-thread/worker splitCHAT.md— chat overlay design (Pixi bubbles, DOM log/input)TESTING.md— determinism seams and renderer testing strategyMODULES.md— inventory of the reference Habbo Retro stack (Arcturus-Community, nitro-react, nitro-renderer) with per-module docs underdocs/modules/