Prepare your game
Build your game locally. Put index.html and every required asset in a ZIP using relative paths. Zip the contents of dist, not the dist folder itself.
index.html
assets/game.js
assets/world.glb
assets/textures.webp
playport.jsonPilot limits: 12 MB per ZIP, 32 MB unpacked and 250 entries. Hidden files, symlinks, encrypted ZIPs and server code are not supported.
Games run in an isolated iframe. Bundle dependencies locally: external APIs, CDNs, background workers and browser-local storage are unavailable in this mode. Use the SDK below for progress.
Download the cloud-save examplePublish from your branch
In your studio, set the repository, branch and output folder. Download the workflow and add it as .github/workflows/playport.yml on that branch. GitHub will build and send the game on push.
The server verifies GitHub’s signature, the game, repository, branch and workflow. No long-lived deployment secret is required. Successful builds go live automatically; failed builds leave the previous version intact.
This version supports github.com with standard OIDC claims and no GitHub Environment. The first deployment pins the immutable repository and owner IDs. The site must be reachable by GitHub over the network.
Keep progress across releases
Player data is stored on the server under account + game + slot. Publishing a release only changes the current build. Players need a GamePort profile to use cloud saves.
await window.GamePort.ready();
const saved = await window.GamePort.load('main');
// Never overwrite a newer format with an older build.
if (saved.schemaVersion > 1) {
throw new Error('Please launch a newer game version.');
}
let revision = saved.revision;
let state = saved.data ?? { level: 1, coins: 0 };
// Save at checkpoints, not every animation frame.
const result = await window.GamePort.save(state, {
slot: 'main', revision, schemaVersion: 1
});
revision = result.revision;
// On save_conflict, load again and reconcile state.Each slot holds up to 64 KB of JSON, with up to 10 slots per player per game. The server keeps up to 10 previous revisions and rejects writes carrying a stale revision.
When your save format changes
Add playport.json to your build root. Increase saveSchemaVersion, migrate the loaded data in your game and pass the new schemaVersion when saving. Migration is never automatic and the old save stays intact until a successful write.
{ "saveSchemaVersion": 2 }An older build cannot overwrite a save using a newer schema. Rolling back the game preserves data, but the creator must ensure compatibility or ask the player to launch a compatible version.