Game modules

A game is a self-contained folder. Everything the game needs lives inside it, nothing outside the folder needs to change when you add, update or remove a game.

games/
└── my-game/
    ├── game.json          manifest (required)
    ├── index.html         entry file (required, name set in game.json)
    ├── cover.png          640×480 cover shown in the catalogue (recommended)
    ├── assets/            scripts, styles, images, audio, fonts, wasm …
    ├── server/            optional PHP routes for this game (see below)
    └── README.md          notes for your team (not served)

Rules

  • Slug = folder name, ^[a-z0-9][a-z0-9-]{1,78}$. Folders starting with _ or . are ignored (_template).
  • Static only. The portal never executes PHP from a game folder, and .php, .sql, .env, .ini files and game.json are not served. Everything else is served with the correct MIME type (including .wasm, .glb, .pck, .unityweb, audio and fonts).
  • Relative paths. Reference your assets relatively (assets/game.js), not with a leading slash. The game is served under /play/{slug}/files/, and your index.html resolves relative URLs correctly from there.
  • Same origin. Games run in an iframe on the portal's own origin with allow-scripts allow-same-origin allow-forms allow-pointer-lock. That is what lets the SDK use the player's session cookie. Do not embed third-party trackers.
  • Size. Keep the first load under a few megabytes where possible. Files are cached for a day; the entry file is never cached.

How files are served

URLBehaviour
/play/{slug}The play shell page (login required). Starts the session, hosts the iframe and the timer.
/play/{slug}/files/{entry}The entry file. Only served when the player may play (logged in, not over the daily limit, premium if required).
/play/{slug}/files/{anything}Assets. Served to anyone, cached 24 h.
/games/{slug}The public game page with description, leaderboard and the Play button.

Direct requests to /games/my-game/index.html are routed to the application and answered with 404, so the only way to launch the game is through the shell.

Engines

Anything that produces a static web build works: plain JS/Canvas/WebGL, Phaser, PixiJS, Three.js, Godot (HTML5 export), Unity WebGL, Unreal pixel-streaming is not supported. For Godot and Unity, put the exported files in the folder, point entry at the generated HTML, and add the SDK <script> to that HTML. Call the SDK from your engine's JavaScript bridge.

Optional server module

If a game needs server logic (turn validation, matchmaking, procedurally generated daily puzzles), add server/routes.php. It must return a closure that receives the router and the slug; routes are mounted under /api/games/{slug}/ and run through the API authentication middleware, so App\Middleware\ApiAuth::$player is available.

<?php
// games/my-game/server/routes.php
use App\Core\Router;
use App\Middleware\ApiAuth;

return static function (Router $r, string $slug): void {
    $r->get('/daily', function () {
        $seed = crc32(gmdate('Y-m-d'));
        return ['ok' => true, 'data' => ['seed' => $seed]];
    });
    $r->post('/turn', function () {
        $player = ApiAuth::player();      // 401 if not logged in
        // validate the turn, store it with App\Core\Database …
        return ['ok' => true, 'data' => ['accepted' => true]];
    });
};

Call it from the game with AllGame.request('GET', '/../games/my-game/daily') or plain fetch('/api/games/my-game/daily', { credentials: 'same-origin', headers: { 'X-Requested-With': 'AllGameSDK' } }).

Server modules can use the platform's App\Core\Database and the models. They may create their own tables; prefix them with the slug (my_game_turns).

Optional server/install.sql

Put CREATE TABLE IF NOT EXISTS … statements in games/{slug}/server/install.sql. The registry runs the file once on sync (and again whenever its content changes), so a game can ship its own schema. Chess Master uses this for its chess_master_matches table.

Multiplayer and invites

Declare "max_players": 2 (or more) in the manifest and the game becomes invitable from the Community page. See Community & invites for how ?invite={id} reaches your game and how to pair the two players.

Versioning and updates

Bump version in game.json on every release and sync. Save states carry their own version number per slot; if you change your save format, read the old shape and migrate it in the game.

Editing a game without touching its folder

Administrators can change texts, category, player counts, leaderboard settings, status, highlight flag, sort order and the cover under Admin → Games → Edit. These values are stored as overrides in the database and win over game.json on every sync. "Remove all edits" returns to the manifest values.

Removing a game

Delete or rename the folder and sync. The game is marked hidden; its scores and save states are kept so it can return later. Administrators can delete data manually if needed.

Last updated October 11, 2026.