Developers

Package format and SDK

A build is one .zip of your web export. It is checked automatically, test-played in a headless browser, reviewed by a person, then served from its own folder on games.playrallyarena.com inside a sandbox. How publishing works →

1. The zip

  • index.html and rallyarena.json at the top (a single wrapping folder is fine — it is removed).
  • Up to 50 MB zipped, 200 MB unpacked, 2,000 files. Files over 30 MB are flagged: they load slowly on phones.
  • Relative paths only, and every file the game needs inside the zip — nothing from CDNs or other sites.
  • Allowed file types: aac, atlas, avif, basis, bin, css, csv, data, fnt, gif, glb, gltf, htm, html, ico, jpeg, jpg, js, json, ktx2, m4a, map, mjs, mp3, mp4, oga, ogg, otf, pck, png, svg, ttf, txt, unityweb, wasm, wav, webm, webp, woff, woff2, xml. Pre-compressed .br / .gz files (Unity) are served with the right encoding. HTML must not be compressed.

2. rallyarena.json

{
  "sdk": 1,
  "orientation": "landscape",
  "aspectRatio": "16:9",
  "input": ["keyboard", "mouse", "touch"],
  "mobile": true
}
  • sdk: always 1 for now.
  • orientation: "landscape", "portrait", "any".
  • aspectRatio: the shape of your canvas, like "16:9" or "9:16". The player keeps it and scales to fit.
  • input: any of "keyboard", "mouse", "touch", "gamepad".
  • mobile: true if it plays well on a phone. Then it is test-played on a phone-sized screen too, and must pass there.

3. The SDK

It is added to every HTML page of your build automatically — you do not need to include it. ready() is the one required call: the test play fails if it does not happen within 30 seconds.

// When your game has loaded and can be played:
RallyArena.ready();

// When a round / level / run starts, and when it ends:
RallyArena.gameplayStart();
RallyArena.gameplayStop();

// Saves: use localStorage as usual — inside the sandbox the SDK provides it,
// and keeps it between visits (up to 256 KB per game). Or explicitly:
RallyArena.storage.setItem('best', '4200');
RallyArena.storage.getItem('best'); // "4200"

// Pause when the player switches tabs:
RallyArena.on('pause', () => game.pause());
RallyArena.on('resume', () => game.resume());

To test on your machine, include it yourself; it does nothing outside RallyArena except record the calls, and a copy in your upload is harmless.

<!-- index.html, while testing on your machine (optional in the upload) -->
<script src="https://playrallyarena.com/sdk/rallyarena-v1.js"></script>

4. The sandbox

Every game runs in a sandboxed iframe with a strict content security policy. In practice:

  • The game can load and fetch its own files, and data: / blob: URLs it creates — nothing else. No servers, no analytics, no multiplayer backends (yet).
  • localStorage works through the SDK and is kept per game. IndexedDB and cookies do not work — engines that save to IndexedDB (Unity’s PlayerPrefs, Godot’s user://) need their saves routed to localStorage.
  • No pop-ups, new windows, forms, or navigating the page. WebAssembly, Web Workers, WebGL, Web Audio and the Gamepad API all work.
  • Audio starts after the player presses Play, so autoplay restrictions do not apply.
  • Games are not cross-origin isolated, so SharedArrayBuffer is unavailable: export Godot 4 with threads off.

5. What is checked

  1. On upload: size and file limits, safe paths, allowed file types, index.html and a valid manifest, no ad networks, analytics or other portals’ SDKs, nothing loaded from other sites.
  2. Test play: a headless Chrome loads the build in the sandbox on a desktop screen (and a phone screen if mobile), waits for ready(), and records errors and anything the sandbox blocked, with screenshots.
  3. Review: a person plays it. It must work, be yours, and suit everyone. You get the reviewer’s note either way.

Updates go through the same steps; the live version keeps running until the new one is approved.