Quickstart

From nothing to a game that passes the platform's checks and is ready to submit: create it from the starter, run it in the dev console, validate it, check it, hand it in. Plan on an afternoon for the first game; most of it is your game.

Not

The SDK, the starter and the tools are packages of the GamePortal repository today, and a game is a folder in it (games/<id>). Every command below runs from the repository root. External publishing (accounts, upload, a developer panel) opens in V2; until then, games come in through the GamePortal team, see Packaging and submission.

What you need #

  • Node.js 22.12 or newer and pnpm 10 (the repository pins the exact version).

  • The repository, installed once with pnpm install.

  • A Chromium for the runner: the one Playwright installs for the repository is used.

1. Create the game #

bash
pnpm create:game my-game --name "My Game" --name-tr "Oyunum"
pnpm install

The id (my-game) becomes the folder games/my-game, the URL segment, the portal page and the prefix of every storage key: lower-case letters, digits and -. pnpm create:game copies templates/game-starter, fills in the id and the names, and prints the steps that connect a finished game to the portal catalogue. The second command links the new workspace package.

What you get is a small, working game (tap targets before they shrink) wired to the portal end to end:

games/my-game/
  index.html            markup: HUD, canvas, card, pause overlay
  manifest.json         what the portal needs to know about the game
  public/CREDITS.txt    rights and credits, shipped in the build: fill it in
  src/host.ts           THE PORTAL WIRING: handshake, saves, scores, events, pause, language, day. Keep it.
  src/constants.ts      ids, versions, tuning numbers; must agree with manifest.json
  src/save.ts           the save: versioned, parsed defensively, merged without loss
  src/pacing.ts         score and event pacing under the SDK limits
  src/world.ts          the example game's rules (pure: no DOM, no clock, no Math.random)
  src/run.ts            title, playing, over: the flow around a round (pure)
  src/render.ts         canvas drawing, fitted to any frame size
  src/main.ts           the shell: DOM, input, ties the above together, exposes the test hook
  test/                 unit tests: rules, flow, save, pacing, manifest, score plausibility

2. Run it in the dev console #

bash
pnpm --filter @gameportal/game-my-game dev

This starts vite build --watch and two servers on two different origins, so the origin checks run for real from the first minute:

WhatAddress
The fake portal and its console (open this)http://localhost:3760/
Your game, in the portal's iframehttp://127.0.0.1:4160/my-game/1.0.0/
Your game on its own, as a top-level page (standalone mode)the same game address, opened in a tab

The game address is served by the real games-host request handler: the same headers, the same <meta name="gameportal:portal-origins">, no cookies. The fake portal is the one the platform's runner uses, so what you see in the console is what check will do. Saving a file rebuilds the game and reloads the frame.

Things to try in the first five minutes (all in Testing):

  • Watch hello, init and ready in the log, and how long they took.

  • Press pause, resume, a language switch and a new day, and see the game react.

  • Edit the init payload: a new player, a returning player, a save from a newer build, a broken save.

  • Delay init for ten seconds and see that the game waits instead of switching to standalone mode.

  • Make the next save fail with conflict, rate_limited or network and see what your game does.

3. Make it yours #

Replace world.ts, run.ts, render.ts and the strings with your game. Keep the shape of main.ts, and keep host.ts as it is unless the SDK contract changes: it is the part that has to be right, and the runner checks it on every run.

Keep manifest.json and src/constants.ts in step (a unit test fails when they drift). Declare every event and score you send in the manifest, and write the plausibility proof for each score (Manifest reference).

Sending a score and an event at the end of a round looks like this:

ts
// a round just ended with 240 points and 18 hits
const ack = await bridge.score("round_score", 240);
if (ack && !ack.ok && ack.error === "rate_limited") {
  // too soon after the previous score: the starter's src/pacing.ts spaces them for you
}
void bridge.event("round_end", { score: 240, hits: 18 });

XP is never in a message: the portal gives XP itself, from play time and from what your events unlock.

4. Validate and check #

bash
pnpm --filter @gameportal/game-my-game test        # your unit tests
pnpm --filter @gameportal/game-my-game validate    # build + the static rules: seconds
pnpm --filter @gameportal/game-my-game check       # build + static rules + the fake-portal runner: 3 to 4 minutes

validate scans the build output (manifest, files, sizes, patterns). check also plays the game in a real browser against the fake portal: 15 scenarios, a 60 second error window. Both write rules-report/<id>.<command>.json and print a summary. A rule is pass, warn, fail, manual (a machine cannot decide; a reviewer will look) or pending (validate leaves the runtime rules for check).

The exit code tells scripts what happened: 0 no blocker failed, 1 a blocker failed, 2 bad usage (for example no build yet), 3 the tool itself failed.

Fix blockers first; the rule id says where to look (R-SDK-*, R-STO-*, R-NET-*, ...). FAQ and troubleshooting lists the failures people hit most. Read every manual line once. A shorter run while you iterate: pnpm --filter @gameportal/game-my-game check --error-window 10000 --startup-runs 1 (the platform's rule is the 60 second window, so run the full one before you submit).

5. Package and submit #

  1. Fill public/CREDITS.txt: who made the code, art, sound and fonts and under which licence, or that there are none (R-CNT-02).

  2. Bump version in manifest.json (and GAME_VERSION, package.json) for every change that ships: a released folder never changes.

  3. Run pnpm --filter @gameportal/game-my-game check once more on the final build.

  4. Hand the game over: the repository folder or the build output, with the report. What the review does with it, and what happens to the release, is in Packaging and submission.

If the game already exists #

You do not have to start from the starter. The integration levels let an existing game join with as little change as it needs:

  • Level 0, wrap: no code change. The portal runs your game in its iframe and gives play-time XP while the game is visible and focused; saves stay in the game's own browser storage.

  • Level 1, bridge: add @gameportal/game-bridge, move saves behind bridge.storage, let the portal own language and pause. A few dozen lines; the sample at the top of the SDK reference is the whole of it.

  • Level 2, deep: scores, the daily challenge metric and game-specific badge events, declared in the manifest.

Details and what each level asks of the game: Packaging and submission.

İlerlemeni kaydet

E-postana bir bağlantı gönderelim ya da Google ile devam et. Misafir olarak kazandıkların hesabına taşınır.