Skip to main content

Game package format

A game is delivered as one folder. This page lists every rule the platform's validator applies to that folder. A game that breaks a rule marked as an error is not published.

The folder at a glance​

my-game/
index.html the page the game starts from
js/ img/ audio/ anything the game loads, referred to by relative path
game.json optional: title, description, controls and other metadata
thumbnail.png optional: 16:9 artwork for the game's card and page

Only index.html (or another entry page, see below) is required. A game can be that single file.

The entry HTML file​

The entry file is the page a visitor's browser loads when they press Play. It is chosen in this order:

  1. The file named by "entry" in game.json, if that field is set. The file must exist in the folder.
  2. Otherwise, a file named index.html or index.htm at the top level of the folder.
  3. Otherwise, the only .html or .htm file at the top level, whatever it is called.

It is an error when:

  • There are several HTML files at the top level and none is index.html. Rename one, or set "entry".
  • There is no HTML file at the top level. If the game's files sit one folder down, move them up a level or set "entry".
  • The entry file does not look like an HTML document. It must contain at least one of an html, body, script or canvas tag, or an HTML doctype.

One limit applies to the entry file in particular: keep it under 6 MB. The platform reads the entry file in order to inspect it, and it does not read HTML or CSS files larger than that. An entry file over the limit is rejected with the message that it could not be read. This matters mostly for single-file games with large assets embedded in the page.

Size limits​

LimitValue
Files in a game2,000
Size of one file50 MB
Size of the whole game300 MB
Length of a file path240 characters
Entry HTML file, in practice6 MB

An empty folder is an error. An empty file produces a warning.

File types​

Only the file types on this list are accepted and served. A file with any other extension, or with none, is an error. Upper and lower case in the extension make no difference.

KindExtensions
Pages and code.html .htm .js .mjs .css .wasm
Data and text.json .txt .xml .csv .map .webmanifest
Images.png .jpg .jpeg .gif .webp .avif .svg .ico .bmp .ktx2 .basis
Audio.mp3 .ogg .oga .opus .wav .m4a .aac .flac
Video.mp4 .webm
Fonts.woff .woff2 .ttf .otf
3D models.glb .gltf
Game and engine data.bin .data .dat .pck .unityweb .atlas .fnt .tmx .tsx .glsl .vert .frag

Each file is served with a fixed content type decided by its extension. .tsx is treated as a tileset file and served as XML, not as script source.

Files that are rejected​

These are errors, with a message naming the file. They exist to stop private material being published by accident.

RejectedExamples
Version-control dataa .git folder
Dependency treesa node_modules folder
Environment and secrets files.env, .env.local, .dev.vars
Keys and certificates.pem .key .p12 .pfx .crt .cer .keystore .jks
Credential filesid_rsa, id_ed25519, .npmrc, .htpasswd, credentials.json, secrets.json
Editor backupsnames ending in ~, .bak, .swp, .orig or .tmp
Server-side or executable code.php .asp .aspx .jsp .cgi .sh .bat .cmd .exe .dll .so .dylib .py .rb .pl
Any other hidden file or folderany name beginning with a dot

Files that are left out​

Some files may sit in the folder without being published. They are skipped quietly.

  • Files for the publisher, at the top level only: game.json, thumbnail.png, thumbnail.jpg, thumbnail.jpeg, thumbnail.webp, and files named README, LICENSE or CHANGELOG with or without an extension. These are read where relevant but never served to players.
  • Operating-system clutter, anywhere in the folder: .DS_Store, Thumbs.db, desktop.ini, __MACOSX, .gitkeep, .gitignore and .gitattributes.

The publisher files are skipped only at the top level. A README.md inside a subfolder, for example, is treated as a game file, and since .md is not an accepted type it is an error.

File names and paths​

Every file path, measured from the top of the folder, must be safe to use in a web address. A path is an error if it:

  • Contains a backslash, a control character, or any of the characters <, >, ", |, ?, *, # or %.
  • Has a folder or file name that ends with a space or a dot.
  • Is longer than 240 characters.

Spaces and parentheses inside a name are accepted.

Two files whose paths differ only by upper and lower case, such as Logo.png and logo.png, are an error. They would collide on systems that ignore case.

Relative paths only​

Refer to every file the game loads by a path relative to the file that refers to it: img/ship.png, not /img/ship.png and not a path on your own disk.

The validator reads the entry page, every other HTML file and every CSS file, and checks each reference it finds. HTML and CSS files larger than 6 MB are not read.

ProblemResult
The referenced file is not in the folderError
The file exists but the reference uses different upper or lower caseError. Addresses are case-sensitive once published.
The reference climbs out of the game folder with ../Error

The references it reads are:

  • In HTML: the source of scripts, images, audio, video, media sources and tracks, frames, embeds and objects; the link target of stylesheets, icons and other linked resources; video posters; and SVG image and use references.
  • In CSS files and style blocks: url(...) values and @import rules.

References to data: and blob: addresses, page fragments beginning with #, and mailto: and tel: links are ignored. So are link tags whose relation is canonical, alternate, author, license, help, dns-prefetch or preconnect.

What the validator cannot see​

Two things are worth testing yourself, because the automatic checks do not cover them.

  • Files loaded by script. A file that your JavaScript requests at run time, for example with fetch or by setting an image's source in code, is not checked. If it is missing, the game fails for players, not at validation.
  • Paths that begin with a slash. A game is not served from the root of its address but from a path that includes its build identifier. A reference such as /img/ship.png therefore does not resolve once published. The validator checks that the file exists but does not flag the leading slash.

A good test for both: serve the folder from a sub-path of a local web server, open the game there with the network otherwise disconnected, and watch the browser console for failed requests.

No external resources​

A reference in HTML or CSS to another website, whether it begins with http://, https:// or //, is an error:

Loads resources from https://cdn.example.com, which the game sandbox blocks. Bundle the files with the game, or add "https://cdn.example.com" to permissions.network in game.json.

The simplest fix is to copy the file into the game folder.

The alternative is to list the origin under permissions.network in game.json. Only https origins can be listed, and a network permission has to be agreed with the team; see Sandbox and permissions.

Warnings​

Warnings do not stop a game from being published. They point at things that will not work, or may not work, once the game is in its sandbox.

The game...Warning
Has no viewport meta tagIt may render tiny on phones.
Registers a service workerA sandboxed game cannot rely on one; it will be ignored or fail.
Uses document.cookieCookies are unreliable inside the sandbox; prefer localStorage.
Tries to navigate the top-level pageThe sandbox blocks this.
Calls alert, confirm or promptBlocked unless permissions.modals is set.
Opens links in new windows or tabsBlocked unless permissions.popups is set.
Calls network APIs such as XMLHttpRequest, WebSocket or fetch with a full addressRequests to origins not listed in permissions.network are blocked.
Contains an empty fileThe file is empty.

These checks look for patterns in the source of the entry HTML file, and only there. They can miss code that is assembled at run time, they can flag code that is present but never runs, and they do not read separate script files at all.

The same is true of what the platform detects automatically about a game: the inputs it uses, its preferred orientation and the abilities it needs. If your game's code lives in separate .js files, state those things in game.json yourself. See the metadata reference and Sandbox and permissions.

The slug​

Every game has a slug: its permanent identifier. It appears in the game's page address and in the name of the subdomain the game is served from, so it cannot be changed later without the game becoming a different game.

By default the slug is the folder name, lower-cased, with anything other than letters and digits turned into hyphens. game.json can set it explicitly. The rules, and the list of reserved words, are in the metadata reference.

Where validation happens​

The same checks run more than once: when the game is prepared for import, and again on the platform's server, which reads the stored files itself and has the final say. A file's size and checksum are verified when it is stored.

A game that fails stays unpublished and nothing already live is changed. Publishing workflow describes what happens after a game passes.