Ship
A scanned, isolated release.
Ship a production browser build. Loki stores it as an immutable release and serves it from a sandbox.
What you upload
game.json- the HTML entrypoint named in the manifest
- bundled JavaScript, CSS, images, fonts, and other static assets
npx lokiplay ship runs the repo’s build script, then archives the output directory. AGENTS.md and .loki/ are not uploaded.
What is rejected
- backend or
serversource - a direct Nakama client
- Socket.IO multiplayer
- inline
<script>tags or inline event handlers - remote
<script src> - remote stylesheets, including Google Fonts
<form>elements- missing
game.jsonor a missing entrypoint
Localhost URLs are a warning, not a pass.
Isolation
Each release is immutable. The play page loads the game in an iframe with sandbox="allow-scripts allow-pointer-lock allow-same-origin".
CSP is strict. Scripts, fonts, and styles must be same-origin. connect-src includes Loki API and multiplayer endpoints, plus up to ten URIs in networkAllowlist. Forms cannot submit. Camera, microphone, geolocation, and payment are off.
Do not add api.lokiplay.cc or the multiplayer host to the allowlist. Use networkAllowlist only for extra origins the game truly needs.
Security review
| Status | Meaning |
|---|---|
ready | Allowed to activate |
ready_with_warnings | Allowed; read the warnings |
security_review_pending | Wait |
blocked | Rejected |
quarantined | Held for operator review |
ship waits, then activates only a ready release, then checks that the playable URL returns a Loki game page (loki:init in the shell).
Playable URL
A successful ship prints a playable URL. Private play requires creator membership or a signed, expiring play invite. Unlisted play is capability-based. Projects are not enumerable. The public catalog is closed.
Activate and replace
Each successful ship is a new immutable deployment. Activating it replaces the project’s live release. You cannot edit files on an old release in place.