App-server
App-server is the dev server that syncs local files to a world via /admin. It is intended for development only and can overwrite world state, so avoid running it against prod targets. For prod/staging, prefer explicit deploys (gamedev apps deploy).
Prerequisites
- Run a world server with
/adminenabled. - Set these env vars for the app-server process (via
.envor.lobby/targets.json):WORLD_URL:- direct runtime:
http://localhost:3000 - platform slug proxy:
https://<host>/worlds/<slug>
- direct runtime:
WORLD_ID(must match the target worldId)ADMIN_CODE(must match the world server, if set)
Start the app-server
# In a project folder, this scaffolds built-ins locally and deploys them.
# Configure .env or .lobby/targets.json first.
gamedev app-server
Notes
- On first run, app-server creates:
apps/(built-in templates + $scene)assets/(downloaded referenced assets)world.json(world layout + per-entity overrides)
- If you want to pull script sources from an existing world, use:
gamedev world export(module-mode sources)gamedev world export --include-built-scripts(legacy single-file scripts)
gamedev devis the recommended entrypoint for continuous sync and will ask for confirmation on prod targets.- No browser Dev Tools / localhost relay is required.
Multi-target config
Define targets in .lobby/targets.json and pass --target <name> to the CLI or app-server.
{
"dev": {
"worldUrl": "https://dev.lobby.ws/worlds/my-world",
"worldId": "dev-world",
"adminCode": "secret",
},
"prod": {
"worldUrl": "https://world.example.com",
"worldId": "prod-world",
"adminCode": "secret",
"confirm": true
}
}
node app-server/server.js --target dev
gamedev dev --target dev
gamedev apps deploy myApp --target prod
Template defaults vs instance overrides
- Blueprint files in
apps/<appName>/*.jsondefine template defaults (what new instances start with). - Per-instance overrides live in
world.jsonunderentities[].propsand are applied to the running world. - Editing instance props in the admin UI updates
world.jsonwhen app-server is running. - Editing
world.jsonwhile app-server is running applies the change back into the world.
Use blueprint JSON for defaults, and use world.json for per-instance tweaks.
Script formats (module-first)
App-server always uploads every .js/.ts under apps/<AppName>/ as scriptFiles. scriptFormat controls how the entry is interpreted:
module(default for new apps): the entry mustexport default (world, app, fetch, props, setTimeout) => { ... }.legacy-body: the entry is a classic script body with imports at the top; the runtime wraps it intoexport default (...) => { ... }.
If scriptFormat is missing, app-server infers it during deploy:
modulewhen the entry exports default.legacy-bodyotherwise (with a warning). The blueprint JSON is not modified.
Use gamedev scripts migrate --module or --legacy-body to tag existing blueprints.
Common workflow
- Edit
apps/<appName>/index.js(orindex.js) and/orapps/<appName>/*.json. - App-server deploys via
/admin(script files uploaded as-is).
Result: Changes appear in-world in ~1–2 seconds without page refresh.
What’s watched by the server
apps/<appName>/**/*.jsandapps/<appName>/**/*.ts— script changes deploy via/adminapps/<appName>/*.json— model/props/meta changes deploy via/adminshared/**/*.jsandshared/**/*.ts— shared module changes deploy only the apps that import themassets/**— if referenced by any blueprint, changes trigger deploy
Tips
- On
version_mismatch, app-server fast-forwards and reapplies local changes, overwriting world state. - Downloaded assets live in the shared
assets/folder and are referenced from blueprint JSON. WORLD_URLshould point to the world base URL (not/admin). If/adminis included, app-server normalizes it automatically.
Deploy safety (locks, snapshots, rollback)
- App-server acquires a deploy lock before applying script changes. If another deploy agent holds the lock, you will see a "locked" error.
- Each deploy creates a snapshot of the affected blueprints. Rollback restores the last snapshot (or a specific snapshot id).
gamedev apps deploy myApp --dry-run
gamedev apps deploy myApp --note "fix font sizing"
gamedev apps rollback
gamedev apps rollback <snapshotId>
For prod targets, the CLI asks for confirmation unless you pass --yes.
Troubleshooting
- Bootstrap didn’t happen: ensure the target world is empty/default or run
gamedev world export(add--include-built-scriptsfor legacy single-file apps). - Unauthorized: ensure
ADMIN_CODEmatches the world serverADMIN_CODE. - Script updates rejected: ensure
ADMIN_CODEmatches and the deploy lock is free. - WORLD_ID mismatch: set
WORLD_IDto match the target world id, or useALLOW_WORLD_ID_CONFIG_MISMATCH=truefor shared-schema prototype runtimes. - Changes not appearing: confirm
apps/<appName>/index.js(or blueprint JSON) is being edited and app-server is connected.