A starter repository for building browser games on Crowded Kingdoms with the CrowdyJS SDK.
The SDK gives you the platform. This repo gives you the rest of a game: an engine-agnostic platform layer, two renderers driven by the same session, a server-authoritative game model, an in-game Crowdy Studio IDE where players write and run their own mods, hosted sign-in (your players sign in on Crowded Kingdoms and come back holding a token for your game -- your page never sees a password), and a one-command Setup that creates your org and app on Crowded Kingdoms — no card, no operator, no infra.
Clone it, run it, then replace the demo scenes with your game.
| Area | What it is | Where |
|---|---|---|
| Holodeck | A three.js hub where players arrive, see each other, chat, and step on pads | src/scenes/holodeck-three/ |
| Paint | A pixi.js program: a shared canvas painted with persisted voxels | src/scenes/program-pixi/ |
| Platform layer | Hosted sign-in, app entry, presence, chunks, save state, chat, proximity webcam (B), model, Studio — engine-agnostic | src/platform/ |
| Adapter boundary | The small GameScene contract both renderers implement |
src/engine/, docs/RENDERER-ADAPTER.md |
| Crowdy Studio | The in-game IDE: players claim a chunk and write SERVER + CLIENT Rust mods | src/platform/studio/, docs/MODDING.md |
| Game model | Kit blueprints (progression, leaderboards) + a hand-authored catalog, seeded idempotently | model/blueprints.mjs |
| Setup | org → free app → access tier → redirect URIs → seed → Studio starter files, from a shell (npm run setup) |
src/platform/onboarding/, scripts/setup.mjs |
| Security headers | COOP/COEP/CSP that make CLIENT mods possible, plus the Permissions-Policy the camera needs, wired into Vite and documented per host | security-headers.mjs, docs/HOSTING.md |
Prerequisites: Node 20+ and a modern browser. Nothing else.
git clone https://github.com/CrowdedKingdoms/the-construct.git
cd the-construct
npm install-
Create your app from a shell. You need a Crowded Kingdoms account (sign up at studio.crowdedkingdoms.com if you do not have one), then:
[email protected] CONSTRUCT_PASSWORD=... \ npm run setup -- --org "My studio" --app "The Construct"
Eight idempotent steps run: organization, free app on shared hosting, a Constructor access tier with the Crowdy Studio code keys, the dev server registered as a redirect URI, an app token, the self-claim grid policy, the game model, and the Studio starter files. It prints an app id; copy
.env.exampleto.env.localand setVITE_APP_IDto it.Why a shell and not the browser: creating an app needs your account's session, and a game on its own domain never holds one -- see step 2.
-
npm run dev, open http://localhost:5175, press Sign in with Crowded Kingdoms. You sign in (or create an account) on Crowded Kingdoms and come straight back holding a token confined to your app. Your page never sees a password: since ck-api v1.88.0 the direct sign-in calls are served only to Crowded Kingdoms' own pages, so this hosted flow is the only one a game on its own domain can use. -
Enter The Construct. You are in the holodeck.
WASDmoves, click to look,Tchats,Eon a pad. Open a second browser (or a friend does) at the same URL — you see each other. -
Step on Load: Paint and press
E: the pixi.js program. Click to paint; the cells replicate live and persist. -
Step on Claim & Studio and press
E: you claim the chunk you stand on and Crowdy Studio opens beside the game. Follow docs/MODDING.md to deploy a mod that runs in the browser — yours and your visitors'.
Everything but VITE_APP_ID is optional: the installed SDK build already knows
the API origin for its tier. When you deploy somewhere other than
http://localhost:5175, register that origin too -- npm run setup -- --origin https://play.example.com, or Studio > Apps > Settings > Sign-in & redirect
URIs. That list is both where sign-in may return your players and the API's
CORS allow-list for your app.
| Command | Purpose |
|---|---|
npm run dev |
Vite dev server with the production security headers |
npm run build / npm run preview |
Production bundle, and serve it locally with the same headers |
npm test |
Unit tests (vitest) + CSP builder tests (node --test) |
npm run test:e2e |
Playwright: boots cross-origin isolated; with CONSTRUCT_E2E=1 and credentials, signs in and opens Studio |
npm run lint / npm run typecheck / npm run format:check |
Quality gates CI runs |
npm run setup -- --org "…" --app "…" [--origin https://…] |
Setup: org, app, tier, redirect URIs, seed; needs CONSTRUCT_EMAIL / CONSTRUCT_PASSWORD |
npm run seed |
Re-deploy the model + Studio starter files to APP_ID after editing model/ or mods/ |
npm run smoke |
Verify an app has everything Setup should have produced |
npm run check:pin |
The CrowdyJS pin is exact and matches the branch tier |
flowchart LR
subgraph platform [src/platform — engine agnostic]
Net[NetworkManager]
Stores[WorldStores]
Session[GameSession]
Studio[StudioService]
Model[ModelService]
Onb[onboarding]
end
subgraph engine [src/engine]
Loop[GameLoop]
Router[SceneRouter]
Input[Input]
end
Holo[holodeck-three] --> Router
Paint[program-pixi] --> Router
Router --> Session
Loop --> Session
Session --> Stores --> Net
Studio --> Net
Model --> Net
Onb --> Net
Net -->|GraphQL + realtime| CK[Crowded Kingdoms]
- Two tokens, one endpoint: an identity session for account and admin work,
a short-lived app-scoped token per game for everything else.
NetworkManagerowns both. Scenes never see a token. - The loop reads the active scene's
localPose()every frame and hands it to the replication store, which sends at 5 Hz on change. Scenes render other players fromsession.players(). That is the whole adapter boundary. - The browser presents intent and renders results. Inventories, scores, grids, and who may run code are decided server-side by the game model and the platform. See docs/ARCHITECTURE.md.
- docs/ARCHITECTURE.md — layers, authority, the boot sequence, what is generic and what is demo
- docs/RENDERER-ADAPTER.md — replacing a scene or the whole renderer
- docs/PLATFORM-MAP.md — game concept → platform surface, with links to the public docs
- docs/MODDING.md — Crowdy Studio: permissions, the CLIENT mod sandbox, templates, visitors, security posture
- docs/NEW-GAME-CHECKLIST.md — turning this into your game
- docs/HOSTING.md — static hosting with the headers CLIENT mods require
- CHANGELOG.md
A new organization gets free apps on shared hosting (three by default) with monthly allowances per app (egress, ingress, compute hours, storage). Nothing here asks for a card. Sustained usage above the allowances bills the org wallet; a player's mods have a free monthly compute trial before their own wallet is involved. Current figures: Shared environment and Player billing.
This repo deploys nothing. npm run build produces a static site you can put
anywhere — with one requirement: the host must send the COOP/COEP headers or
CLIENT mods will not run (the game says so on screen). Recipes in
docs/HOSTING.md.
dev, test and prod track the three Crowded Kingdoms tiers. Each pins the
exact CrowdyJS build published for its tier (X.Y.Z-dev.N, X.Y.Z-test.N,
X.Y.Z), because each build carries its tier's API origin. Clone prod
unless you are working with the platform team. npm run check:pin enforces it.
MIT — see LICENSE. The Crowded Kingdoms platform and the CrowdyJS SDK have their own terms.