Packaging and submission

What a finished game looks like on disk, how big it may be, what you owe the portal in licences and credits, how versions work, what happens to a game after you hand it over, and which integration level your game can join at.

Not

Self-service submission (accounts, upload, a developer panel, play and retention metrics) opens in V2. Until then games are handed to the GamePortal team and go through the same checks, review and release steps described here. Nothing on this page needs the V2 panel: it is the process that panel will wrap.

The build output #

A game is a folder of static files. Whatever your toolchain, pnpm build ends in a folder like this (Vite's dist/):

dist/
  index.html          the entry (manifest `entry`), at the root
  manifest.json       valid against the manifest schema, next to index.html
  CREDITS.txt         rights and credits (any of CREDITS, LICENSE, NOTICE, PROVENANCE, third-party notices)
  assets/...          scripts, styles, images, audio, fonts: everything the game loads

Rules of the folder (all checked by validate):

  • Static files only. No server code, no rewrites, no build step at serve time (R-BLD-01).

  • Relative paths. Every file is referenced as ./... or assets/..., never /assets/... and never with a host name, because the game is served from /<id>/<version>/ and must run from any such path (R-BLD-05). In Vite set base: "./".

  • manifest.json next to the entry, with id and version matching the release folder (R-MAN-01, R-BLD-06).

  • No dotfiles or dot-folders. games-host refuses every path segment that starts with a dot (no .well-known, no stray .DS_Store you rely on).

  • Known file types only. games-host serves these extensions with a proper content type: html, htm, js, mjs, css, json, webmanifest, map, txt, xml, svg, png, jpg, jpeg, gif, webp, avif, ico, woff, woff2, ttf, otf, mp3, ogg, wav, m4a, mp4, webm, wasm. Anything else is served as application/octet-stream, and with nosniff the browser refuses to run such a script or style (R-BLD-07).

  • No inline scripts. The target Content-Security-Policy allows scripts from the game's own folder only (R-SEC-03).

  • No service worker, no cookies, no SharedArrayBuffer. The games origin is shared by every game, games-host sends no COOP/COEP headers and no cookies (R-SEC-04, R-STO-02, R-BLD-08).

Size budgets #

BudgetLimitRule
First load until ready, compressed (gzip)1536 KBR-BLD-02, blocker
First load of a session: "quick" game, compressed300 KBR-BLD-03, warning
The whole build output, uncompressed50 MBR-BLD-04, blocker
A saved game256 KBR-STO-04, blocker

"First load" is everything the browser downloads before the game sends ready, as gzip-compressed bytes. Load later levels, music and large art lazily, after ready. validate gives an early static estimate; check measures what really loads in the browser, which is the number that counts. The platform also wants ready within 3 seconds of the frame starting to load (R-SDK-02).

Assets and licences #

  • Code and every third-party asset need a stated licence and source. List them in CREDITS.txt: name, author, licence, source address. If there are none, say so. Libraries that carry a licence banner in the build are noticed by the scan. A reviewer reads this file (R-CNT-02).

  • No other brand's names, art or text. No lookalikes of someone else's game.

  • Bundle your fonts and sounds. The game may not contact any other host: no font CDN, no analytics, no ad network (R-NET-02, R-NET-04, R-CNT-01). Synthesized sound (Web Audio) and art drawn in code keep a game small and licence-free.

  • No purchases, donations or outbound links such as store pages, social media or "more games" (R-CNT-04).

  • Content. Stay inside the portal's content rules: no real-money gambling, sexual content, hate, graphic violence or anything above the portal's age rating; the audience is 13 and older (R-CNT-03).

  • You keep your code and your rights. The portal hosts and shows the game; it does not take ownership of it. The legal terms of the developer programme are published when it opens.

Versioning and releases #

  • version in the manifest is semver (1.2.0; a suffix such as 1.2.0-beta.1 is allowed). Every change that ships is a new version. The same version string is in manifest.json, in hello.gameVersion and in the release folder (R-BLD-06).

  • A released folder never changes. games-host serves /<id>/<version>/ with a one-year immutable cache for everything except HTML, which always revalidates. A release is recorded with a SHA-256 of its files; releasing the same version with different content is refused.

  • version is not saveVersion. version is the release of the game; saveVersion is the format of the save. A release that does not change the save format keeps saveVersion; raising it needs an upgrade step (save formats) and it never goes down.

  • Old versions stay online. Every released version stays reachable at its own address, so going back is cheap.

What the team does with a version (you do not run these, but it explains the words you will see):

StepCommand (team)Effect
Archivepnpm games:archive <id>Copies the build into the immutable release archive and records its SHA-256.
Publish files(deploy of the games project)The version is reachable at /<id>/<version>/. Players see nothing yet.
Recordpnpm games:release <id> <version>Registers the version in the database. A new game is created in staging; for a game that is already live the version is only recorded and players keep playing the old one.
Acceptpnpm games:accept <id>The review passed: a staging game becomes live.
Promotepnpm games:promote <id> <version>Makes a recorded version the one players get.
Roll backpnpm games:rollback <id>Returns to the previous version in one change; no files move.

A game in staging is invisible to players, search engines and the catalogue; only the team can open it. Who plays which version is a value in the portal's database, so promoting and rolling back take effect within about half a minute, and a player who is mid-game keeps the version they started until they reload.

How games are served #

games-host is a static host on its own origin. For every response, including errors:

HeaderValueWhy
Content-Security-Policyframe-ancestors <portal origin>Only the portal can embed a game.
X-Content-Type-OptionsnosniffThe browser trusts the content type, so a text file cannot run as a script.
Referrer-Policyno-referrerThe game's address is not leaked to anything it links to.
Cache-ControlHTML and directory paths no-cache; everything else public, max-age=31536000, immutable; not found no-storeVersioned folders never change, so assets cache for a year.

It never sets a cookie. It adds <meta name="gameportal:portal-origins" content="..."> to every HTML page, with the portal origins the game may talk to; the bridge reads it. Paths with .., backslashes, NUL bytes or dot segments are refused.

Games from outside developers get more (the games of the GamePortal team move to the same policy one by one):

Header or behaviourValueWhy
Content-Security-Policyframe-ancestors <portal origin> followed by the target policy: default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; font-src 'self' data:; media-src 'self' data: blob:; connect-src 'self'; worker-src 'self'; frame-src 'none'; object-src 'none'; base-uri 'none'; form-action 'none'The browser itself enforces the network and code rules: no other host, no inline script, no eval (R-SEC-03, R-NET-02, R-NET-03).
Permissions-Policycamera=(), microphone=(), geolocation=(), payment=(), usb=()Device features are never available to a game.
Opened directly (a top-level page)403The game is shown only inside the portal frame.
Service worker script403 for every gameR-SEC-04.
A version that was taken down410 GoneSee "Review, updates and takedown" below.

The portal also watches the frame: if the game navigates its own frame to a page that does not say hello, the portal closes it within two seconds and shows its retry screen. Run pnpm check and the game already runs under this policy (the runner reports every violation).

What the review does #

 you hand in the game
        │
        ▼
 1. automated checks      the same rules runner as `pnpm check`: manifest, files, sizes, patterns,
        │                 fake-portal scenarios, a 60 s error window. Blockers fail the game here.
        ▼
 2. AI integrator         (a game that comes as a repository, HTML or ZIP, and today only for the team)
        │                 analyses it, adds the bridge and the manifest as a patch at the highest level that
        │                 passes; a failed check goes back to it for up to three tries, then the level drops
        ▼
 3. human review          the rules machines cannot decide: content and age, rights, Turkish and English
        │                 texts, feel on a phone; the reviewer sees the report, the patch and a preview
        ▼
 4. staging, then live    the team accepts; the version goes live and is promoted; rollback stays one step away

The AI integrator never approves anything. It is a tool that writes a patch. The checks (step 1 again, in a separate sandbox) decide whether the patch is allowed to continue, and a person decides whether the game goes live. It runs in an isolated sandbox with no keys or tokens, with network access only to the model API and package registries, and its only output is a patch and a report; the text of a repository (a README that says "ignore the rules") is data, never an instruction. It starts with the highest level it can reach safely and lowers the level when the checks keep failing, and when even that fails it hands the work to a person. Applying it to games from external developers is the V2 step.

The review target for external games is 48 hours from a complete submission. The report you got from pnpm check is what the reviewer starts from, so a game that passes it with no blocker and no unexplained warning is a fast review.

Review, updates and takedown #

The full policy (in Turkish) is the portal's publishing policy, docs/PUBLISHING-POLICY.md; its machine-readable part is @gameportal/sdk-types/publishing. In short:

  • What you provide with a submission. Contact details and a security contact reachable within 24 hours; a licence statement (who owns the code, its SPDX licence, the credits file in the build, and that you may publish everything and allow the portal to host and show it); a short content questionnaire (the audience is 13 and older; graphic violence, strong language, explicit content and depicted drug use are refused); a privacy statement (no personal data, no other hosts, no analytics, no ads); release notes in Turkish and English. On request, the source code or a source map.

  • No automatic approval. The checks can refuse a build, never accept it. A reviewer approves to staging, a publisher makes it live. A new game starts unlisted for a few days, depending on your account's trust level.

  • Every update is reviewed. A version never changes once released. Small updates of an established account get a review of the changes (files, manifest, rules that got worse); a loosened score or challenge limit, a new entry file, a worse security, network, privacy or content rule, or a mostly new build get the full review. Changing the game id, lowering saveVersion or the SDK major is refused.

  • Obfuscation and mining. Minified code is fine; obfuscated code (R-SEC-07) and anything that mines or runs proof-of-work (R-SEC-06) are not.

  • Takedown. A version can be taken down at once for malware, data exfiltration, mining or phishing, and after a notice for other breaches (tracking or ads, content, age rating, copyright, trademark, privacy, security). Players get the previous clean version or the game is hidden; the address answers 410. You are told the reason and a case reference.

  • Appeal. One appeal per takedown, within 14 days; a person other than the one who took the game down answers within 7 days.

  • Trust levels. New accounts have small upload and queue limits and always get the full review; limits grow with games that stay live without breaches, and shrink after a breach.

Integration levels #

The integration levels let a game join with as little change as it needs. The AI integrator aims at the highest level it can reach safely and drops one level when a check fails.

LevelWhat happensCode changeWhich games
0, wrapThe game runs in the portal's iframe as it is. The portal gives play-time XP and the "new game" XP while the game is visible and focused. Saves stay in the game's own browser storage.None.Any static HTML5 game. Built engine output (for example Unity WebGL) mostly stays here: the bridge would need a plugin on the engine side.
1, bridgeThe bridge is added: saves move behind bridge.storage (cloud save, no loss on a new device), language and pause come from the portal.Small, often an automatic patch.Games whose save logic can be found: single-file games and Vite, Phaser, Pixi or Three.js builds.
2, deepScores, the daily challenge metric and game-specific badge events are declared in the manifest and sent.Needs an understanding of the game's rules: proposed by the AI, approved by a person.Games worth the extra work. The portal's own games are made at this level.

What each level asks of the game is in the rule checklists by level. In short: security, network, build and content rules apply to every level; Level 1 adds the handshake, saves, language, pause and timing rules; Level 2 adds the manifest's events, scores and challenge rules. A Level 0 game must still open without errors outside the portal and must never post to "*".

Submission checklist #

  • pnpm check ends with no blocker, no unexplained warning, and you have read every manual line.

  • manifest.json is complete, matches your constants and the release version, and declares every event and score you send.

  • Every score mode has a maxPerSecond that you derived from the rules and proved with a test.

  • CREDITS.txt lists the licence and source of the code and of every asset.

  • Turkish and English texts for every player-visible string, the catalogue name, a one-line description and tags.

  • Cover pictures (a wide one and a square one) and, if you have them, screenshots.

  • The build runs from any /<id>/<version>/ path and opens on its own without errors.

  • The first load is under budget and ready comes in about 3 seconds.

  • You can name the level you are aiming for and why.

İ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.