Ship13 min read

Packaging and upload

The zip format, size limits, allowed file types, store art, and every upload error message with what it means and how to fix it.

On this page9 sections

Players install your game as a zip, unpacked on their phone, and play it offline. This page is everything about that zip, plus your store page art, plus every error the upload can give you.

The short version#

  • One .zip, with index.html at the top.
  • Every file inside it: scripts, images, sounds, fonts. Nothing loaded from the internet.
  • Relative paths only: img/hero.png, never /img/hero.png.
  • Allowed file types only (list below).
  • At most 50 MB zipped, 150 MB unpacked, 2000 files.

The zip format#

Here's a typical game folder and the zip made from it:

my-game.zipText
index.html            <- must be at the top
twiddleplay-sdk.js    <- your copy of the SDK
game.js
style.css
assets/
  sprites.png
  music.ogg
  font.woff2
CREDITS.txt           <- licenses for free assets

What the server does with your zip:

  • Looks for index.html at the top. If every file sits inside one top folder (like my-game/index.html), that folder is stripped for you, so zipping the folder itself also works.
  • Drops __MACOSX/ and .DS_Store files that macOS adds. You don't need to remove them.
  • Re-packs your files into a clean zip that the app downloads, and records its fingerprint (SHA-256) so the phone can check the download.

How to make the zip#

1. Open your game folder.
2. Select everything inside it (Ctrl+A).
3. Right-click > Send to > Compressed (zipped) folder.

Limits#

Limit Value
Zip size 50 MB
Unpacked size (all files added up) 150 MB
Number of files 2000
Uploads (zips, icons and screenshots together) 20 per hour

Current upload limits, straight from the server

Zip fileup to 50 MB
Unpacked gameup to 150 MB
Files in the zipup to 2,000
IconPNG, JPG or WebP · square (±2%) · 256–1024 px · up to 1 MB
ScreenshotsPNG, JPG or WebP · up to 2 MB each · longest side up to 4096 px · up to 6

The server counts the real bytes as it unpacks; it doesn't trust the sizes written in the zip. Smaller is better: players download your game on mobile data, and the upload page warns you when your game unpacks to more than 60% of the limit.

Allowed file types#

Only these extensions are allowed. Anything else rejects the whole upload.

Kind Extensions
Web and code html htm js mjs cjs css json map wasm webmanifest manifest
Images png jpg jpeg gif webp avif svg ico bmp
Audio mp3 ogg oga wav m4a aac flac opus
Video mp4 webm
Fonts woff woff2 ttf otf eot
Data and engines txt xml csv md data glb gltf bin atlas fnt plist unityweb pck

The exact list, for copying into a script:

allowed extensionsText
html htm js mjs cjs css json map png jpg jpeg gif webp avif svg ico bmp mp3 ogg oga wav m4a aac flac opus mp4 webm woff woff2 ttf otf eot txt xml csv md wasm data glb gltf bin atlas fnt plist webmanifest manifest unityweb pck

Things that are not allowed, and what to do instead:

You have Do this
LICENSE, README (no extension) Rename to LICENSE.txt, README.txt.
.psd, .aseprite, .blend, .tiled, .tmx source files Leave them out. Export what the game actually loads (PNG, JSON).
.gz, .br pre-compressed files Turn compression off in your engine (see Unity).
.hdr, .exr, .ktx2, .basis textures Convert to PNG, JPG or WebP.
.zip inside the zip Unzip it into folders.
.php, .py, .exe and other programs Leave them out. Only the browser runs your game.

Relative paths#

Your game is not served from the top of a website. It's served from a sub-folder like:

Text
https://<games server>/play/g/<gameId>/<version>/index.html

So a path that starts with / points at the wrong place:

index.htmlHTML
<!-- Good: relative to index.html -->
<img src="img/hero.png">
<script src="game.js"></script>
<link rel="stylesheet" href="./style.css">

<!-- Broken on Twiddle Play: starts at the top of the server -->
<img src="/img/hero.png">
<script src="/game.js"></script>

The same goes for paths in JavaScript and CSS:

game.jsJavaScript
heroImage.src = 'img/hero.png';          // good
// heroImage.src = '/img/hero.png';      // broken
style.cssCSS
/* Paths in CSS are relative to the CSS file */
@font-face { font-family: Pixel; src: url('fonts/pixel.woff2'); }

The only path that should start with / is the platform SDK tag, /sdk/v1/twiddleplay.js.

Offline and self-contained#

Players install your game and often play with no connection. So:

  • Bundle every script and library. No <script src="https://cdn...">. Download the library file into your folder.
  • Bundle your fonts. No Google Fonts links. Download the .woff2 files and use @font-face.
  • No remote config, leaderboards, analytics or ad networks. Only Twiddle Play ads, through the SDK.
  • No links to other websites. Games can't navigate away; the app blocks it.

The upload check lists every outside server your files mention (see below), and reviewers reject games that need the internet.

The upload checks#

After a successful upload, your version shows these checks. The reviewer sees them too.

Check What it looks at What you want
Size Zip size and unpacked size, against the limits. "Light enough to download quickly, even on mobile data."
Files How many files, out of 2000. Well under the limit.
SDK detected Whether any .html, .js, .mjs or .cjs file mentions TwiddlePlay. SDK detected. If it says SDK not found and your ads are on, no ads can ever show.
Works offline Every http:// or https:// address in your .html, .js and .css files (the SDK's own URL and www.w3.org are ignored). Works offline. Otherwise it lists each host, like fonts.googleapis.com.
Largest files Your five biggest files. Nothing surprisingly big.

Your store page#

The Store page tab is what players see in the app. Fill it in before you submit.

Field Rules
Title 2 to 60 characters.
Tagline Up to 80 characters. Required to submit.
Description Up to 4000 characters. At least 20 characters to submit.
Category Puzzle, Arcade, Action, Casual, Word, Board, Sports, Racing, Strategy, Educational or Other.
Age rating All ages, 12+ or 16+. Be honest: see Review guidelines.
Orientation Portrait, Landscape or Any. The app locks the screen to it.
Ads On or off. You can switch this later in Settings.
Icon Required to submit. Rules below.
Screenshots Optional, up to 6. The first one leads your store page.

Icon#

  • PNG, JPG or WebP.
  • Square (width and height within 2% of each other).
  • At least 256×256 and at most 1024×1024 pixels. 512×512 looks best.
  • At most 1 MB.
  • Your game's face on every shelf: bold, simple, no tiny text.

Screenshots#

  • PNG, JPG or WebP, up to 6.
  • At most 2 MB each, and the longest side at most 4096 pixels.
  • 1080×1920 for portrait games, 1920×1080 for landscape.
  • Take them from real gameplay. Drag to reorder them on the store page.

Images that are too big are rejected, never resized for you. If a screenshot is over 2 MB, export it as JPG or WebP.

Every error message, and how to fix it#

These are the exact messages the upload, store page and submit steps can show. Parts in {curly braces} are filled in with your file names and numbers.

Zip upload errors#

Message What it means How to fix it
{file} isn't a .zip. You dropped a file that isn't a .zip on the upload box. Zip your build folder's contents and drop the .zip.
The zip is {size}. The limit is 50.0 MB. The file is over the zip size limit. Compress images (WebP) and audio (OGG/MP3), and drop source files you don't ship.
This zip is {size}. The limit is 50 MB. Same as above, caught while reading the zip. Same as above.
The zip is empty. / The uploaded file is empty. The file has 0 bytes. Re-create the zip and try again.
That file isn't a valid .zip archive. It's not a zip (maybe a .rar or .7z renamed to .zip), or it's damaged. Make a real zip with your system's zip tool.
The zip couldn't be read. Re-create it with a standard zip tool and try again. The zip is damaged in a way the server can't read. Make a fresh zip with Windows, macOS or zip.
The zip is password-protected. Upload an unencrypted zip. You set a password on the zip. Create the zip without a password.
The zip uses an unsupported compression method. Use standard (deflate) zip. Your zip tool used an unusual compression (like LZMA or "ultra" in 7-Zip). Use the standard "Deflate" method (the default in most tools).
"{name}" is an absolute path. Every file must be relative to the game folder. An entry name starts with / or a drive letter like C:. Re-create the zip from inside your build folder.
"{name}" tries to escape the game folder with "..". Remove it and zip again. An entry name contains ... Re-create the zip from inside your build folder.
"{name}" tries to escape the game folder. Same problem, found while unpacking. Re-create the zip from inside your build folder.
"{name}" uses backslashes. Re-create the zip with a standard zip tool. A tool wrote Windows \ paths into the zip. Re-zip with Windows' built-in zip, macOS, or zip.
"{name}" has an empty or "." path segment. Re-create the zip. A name like assets//hero.png or ./hero.png inside the zip. Re-create the zip with a standard tool.
"{name}" is a symbolic link. Zips may only contain regular files. The zip contains a symlink (shortcut). Replace symlinks with real files before zipping.
".{ext}" files aren't allowed (found "{name}"). Allowed: web pages, scripts, styles, images, audio, video, fonts, data and wasm files. A file type that isn't on the allowed list. Remove the file, or convert it. Licenses and notes need a .txt extension.
Files without an extension aren't allowed (found "{name}"). Allowed: web pages, scripts, styles, images, audio, video, fonts, data and wasm files. A file with no extension, like LICENSE. Rename it, for example LICENSE.txt, or remove it.
The zip holds more than 2000 files. Bundle or trim your assets. Too many files. Bundle scripts, or pack sprites into atlases.
The game unpacks to more than 150 MB. Shrink assets and try again. All files added up are over the unpacked limit. Compress images and audio, and remove unused assets.
The game unpacks to more than 150 MB. Same, found while unpacking (the zip's own size info was wrong). Same as above.
The zip has no files in it. The zip only has folders, or only __MACOSX and .DS_Store. Zip the files themselves.
"{path}" appears twice in the zip. Two entries with the same path. Re-create the zip from your folder.
"{name}" clashes with another file or folder of the same name (names are compared ignoring case). Rename one and zip again. Two names that differ only by upper/lower case (Hero.png and hero.png), or a file and a folder with the same name. Rename one and fix your code to match.
No index.html at the top of the zip. Put index.html at the root (or inside one single top folder). There's no index.html where the server looks. Put index.html at the top of the zip.
... Found "{path}" — move it to the top level of the zip. Same, and the server found your index.html deeper down, like build/dist/index.html. Zip the contents of the folder that holds index.html.

Account and limit errors#

Message What it means How to fix it
Too many attempts. Try again in {N} seconds. (or minutes) You made more than 20 uploads (zips, icons and screenshots together) in the last hour. Wait the time shown, then try again.
This game is suspended. Contact support to restore it. The review team suspended this game, so uploads are paused. Contact support.
Couldn't read the upload. Try again. The upload was cut off or garbled on the way. Try again on a steadier connection.
Game not found. The game doesn't exist or isn't yours (for example, you're logged in with another account). Check which account you're using.

Icon and screenshot errors#

Message What it means How to fix it
Icons must be PNG, JPG or WebP. / Screenshots must be PNG, JPG or WebP. Wrong file type. Export as PNG, JPG or WebP.
The {icon or screenshot} must be PNG, JPG or WebP (got {type}). The file's real format is something else, like GIF, whatever its name says. Export as PNG, JPG or WebP.
We couldn't read that image. Try PNG, JPG or WebP. / The {icon or screenshot} isn't a readable image. Use PNG, JPG or WebP. The file is damaged or isn't an image. Export it again.
Couldn't read the {icon or screenshot}'s dimensions. The image has no readable width or height. Export it again from an image editor.
That file is {size}. Icons can be 1 MB at most. Try exporting a PNG at 512×512. The icon file is over 1 MB (checked in your browser before uploading). Export a PNG at 512×512, or use WebP.
The icon is {size}. The limit is 1 MB. (or The limit is 1.0 MB.) The same, checked by the server. Same as above.
Icons must be square. This one is {w}×{h}. Crop it to a square first. / The icon must be square (it is {w}×{h}). Width and height differ by more than 2%. Crop it to a square.
Icons need at least 256×256 px. This one is {w}×{h}. 512×512 looks best. / The icon must be at least 256×256 px (it is {w}×{h}). 512×512 looks best. Too small. Export at 512×512.
The icon is {w}×{h} px. The largest allowed is 1024×1024 px; 512×512 looks best. Too big in pixels. Resize to 512×512.
{file} is {size}. Screenshots can be 2 MB each. / That screenshot is {size}. The limit is 2 MB each. Over 2 MB. Export as JPG or WebP to shrink it.
That screenshot is {w}×{h} px. The longest side can be at most 4096 px; 1080×1920 works well. Too big in pixels. Resize to 1080×1920 (or 1920×1080).
Only {n} more fit. Up to 6 screenshots. You picked more screenshots than there's room for; only the first ones are added. Delete one to make room, then add the rest.
You can have up to 6 screenshots. Delete one first. You already have 6. Delete one, then add the new one.
Upload at most 6 files at once. You picked more than 6 screenshots in one go. Pick 6 or fewer.

Store page errors#

Message What it means How to fix it
Give your game a title (2+ characters). The title is empty or one character. Type a longer title.
Keep the title under 60 characters. Title too long. Shorten it.
Taglines are 80 characters max. Tagline too long. Shorten it to one punchy line.
Descriptions are 4000 characters max. Description too long. Trim it.
This game is suspended and can't be edited. The review team suspended the game. Contact support.

Submit errors#

Message What it means How to fix it
Finish the store page first: Add an icon (square, at least 256×256). No icon yet. Upload an icon on the Store page tab.
Finish the store page first: Write a tagline. Tagline is empty. Write a tagline.
Finish the store page first: Write a description (20+ characters). Description is shorter than 20 characters. Write a real description.
Version {n} is {status}; upload a new version instead. That version was already reviewed or replaced (for example, it was rejected). Upload a new zip; it becomes a new version you can submit.
Version {n} is already live; submit a newer version. You tried to submit a version that isn't newer than the live one. Upload a new zip and submit that.
This game is unpublished. Republish it first, then submit the new version. You unpublished the game in Settings. Republish it in Settings, then submit.
This game is suspended, so new versions can't be submitted. The review team suspended the game. Contact support.
This version changed while submitting. Refresh and try again. Something changed the version at the same moment (like a second tab). Refresh the page and try again.