
Platform Requirements
The canonical list of the platform's technical requirements: every constraint and number lives here; other articles link here for the details. The same fact set is served machine-readable by the minit_get_requirements tool of the Minit MCP Server. Connect it to validate your game as you build.
In short
- One self-contained ZIP with
index.htmlat its root, 50 MB at most (aim for under 5 MB), portrait and touch-first.- Call
reportResultexactly once when the run ends.- No
localStorage, cookies,fetch, external assets, device hardware or navigation away from the page. Per-player data goes through userData.- Hard requirements get an upload rejected. Recommendations make the game load faster and play better.
How to read this page
- Hard requirement: enforced. Violating one gets the upload rejected, fails review, or breaks the game on players' devices.
- Recommendation: not enforced, but makes your game load faster, play better, and reach more players.
Bundle
Your game ships as a single ZIP uploaded in Minit Studio. See Your First Game for the upload flow.
Hard requirements
- The bundle must be a ZIP file. A single self-contained
.htmlfile is also accepted at upload — Studio packs it into a ZIP client-side (using that file as the rootindex.html) before the same validation below applies. - The uploaded ZIP must not exceed 50 MB. For a single-file HTML build this is checked twice: against the original
.htmlfile you pick, before Studio packs it (so an already-oversized file never reaches the packer), and again against the packed ZIP itself — the packed archive is what actually gets uploaded and enforced server-side, and packing occasionally grows an already-dense file (e.g. one with large base64-embedded media) rather than shrinking it. index.htmlmust sit at the root of the ZIP, not inside a sub-folder.- The ZIP must contain JavaScript: at least one
.jsfile, or a self-containedindex.htmlwith an inline<script>block. index.htmlmust include a<script>tag, external or inline:
<script src="js/game.js"></script>
<script>
// game code inline
</script>
- The bundle must be self-contained: every file the game needs (JS, CSS, images, audio, fonts) inside the ZIP. No CDN URLs or remote fetches at runtime.
- Exception: an MRAID playable's
mraid.jsreference. An MRAID (Mobile Rich Media Ad Interface) playable conventionally has<script src="mraid.js">(whose filename is exactlymraid.js— any folder, case-insensitive, but not a look-alike likecustom-mraid.js) without shipping that file — the Minit Games app supplies a compatiblewindow.mraidshim at runtime, so the reference is allowed to resolve to nothing. Every other missing script reference still fails validation.
- Exception: an MRAID playable's
Recommendations
- Keep the bundle under 5 MB. 50 MB is the ceiling, not the target.
Tip: Compress your assets before zipping. Audio bitrate and image resolution are usually the biggest wins.
Viewport & rendering
Games render full-screen inside a mobile WebView.
Hard requirements
-
Portrait orientation only.
-
overflow: hiddenon the document body.
body { overflow: hidden; }
- The canvas (or game container) must fill the viewport.
canvas { display: block; width: 100%; height: 100%; touch-action: none; }
- Cap the frame rate at 60 FPS and use delta-time so game speed is frame-rate-independent:
const FRAME_TIME = 1000 / 60; // skip the frame if elapsed < FRAME_TIME
A game that stays responsive to any portrait aspect ratio and meets every Hard requirement above is still accepted — the fixed-surface convention below is a recommendation, not a gate.
Recommendations
- Author against the fixed 960 × 1480 design surface. Author every position, size, and hitbox in that space; never derive a gameplay coordinate from the raw viewport dimensions.
- Hold the whole game in one wrapper element and scale it with a single uniform CSS
transform: scale(...). Never compute separate x and y factors — non-uniform scale distorts art and breaks hit-testing. - Cap crop at about 5% per axis, fitting/letterboxing instead when it would exceed that, and keep anything that must stay visible inside the central 90%.
- Tap targets must survive the scale-down — check the scaled size, not the authored one. 44 CSS px on a narrow phone (~390 px wide) is ~108 px on the 960-wide surface.
- Pin the viewport meta tag, so the page scale is fixed at the moment your scaling code first reads it:
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover" />
maximum-scale=1 and user-scalable=no are the load-bearing pair — they are what pins the page scale.
- Re-run your scaler when the viewport changes: listen for
resize,orientationchange,visualViewport's own resize event, and aResizeObserveron the document root, since the host can adjust the viewport after your page loads. Keep the wrappervisibility: hiddenin CSS until your first layout pass reveals it, so the player never sees an unscaled first frame.
Tip: The SDK README's "Screen, viewport, and scaling" section has the full recipe — a ready-to-use
layout()function, the viewport-pinning gotcha, and whyinitializeSDK({ metaTags: true })can silently strip a pinned viewport meta. See Install the Minit SDK or the@minit-games/sdkpackage.
Forbidden APIs
All hard requirements. Games must not use:
localStoragesessionStoragefetch()XMLHttpRequest- External CDN resources: no scripts, stylesheets, fonts, or other assets from external URLs
- Device hardware APIs: no camera, microphone, GPS, accelerometer
- Cookies
- Navigation and links: no
<a href>to other pages,window.open,location.href/assign/replace/reload, or<meta http-equiv="refresh">. The game must stay on its own document for the whole play — the host detects a second document load and tears the game down.
Tip: To persist something for a player (a best score, a preference), use the SDK's userData API. See Saving User Data for the API and Remember Your Players for what to keep there. To hand a result back to the host, call the SDK's
reportResult(...)instead of any navigation — see Reporting Results.
SDK requirements
Talk to the platform through the Minit SDK: @minit-games/sdk for HTML5/JS games, or your engine's Minit SDK (Unity, Godot, Defold, PlayCanvas).
Hard requirements
- Signal readiness when your game can be played (see Game Ready Signal).
- Call
reportResult(score)exactly once when the game ends.
import { reportResult } from '@minit-games/sdk';
reportResult(score);
scoremust be a number OR a string, nevernull/undefined. A number feeds leaderboards and, for score/time Result Types (not Group), the automatic star rating; no required range, higher wins by default, and the Game's configuration can invert this. A string is shown as-is on the result screen, with no leaderboard or star rating. Full API: Reporting Results.
Recommendations
- Signal readiness when your game can be played (see Game Ready Signal). It is optional: if the signal does not arrive within 5 seconds, the platform reveals the game anyway.
- Pass a short
flavorText: a caption of up to 64 characters shown alongside the score. Longer values are silently truncated.
reportResult(12500, { flavorText: "Caught 12 fish!" });
- Time the
delayoption (ms) to your closing animation, typically 500–1000 ms. - Bundle the SDK into your build: HTML5/JS games import
@minit-games/sdkfrom npm; don't load the SDK from an external<script>URL. Without a bundler, vendor the SDK's modules into your project and import them as native ES modules, as minit-template-vanilla does.
For every creator-facing size and length cap, including upload failure modes, see Limits & Constraints FAQ.
Controls
Games run on phones: touch is the primary input, and every action must work by touch.
Hard requirements
- Every action works with touch / pointer events. No hover: it never fires on touch screens.
document.addEventListener('pointerdown', handler);
- Keyboard only as an extra input (for example for desktop play), never as the only way to do something.
Recommendations
- Use pointer events (
pointerdown,pointermove,pointerup): they cover touch and mouse, so the game stays testable in a desktop browser.
canvas.addEventListener('pointermove', (e) => { e.preventDefault(); });
- Set
touch-action: noneon the canvas so the browser doesn't intercept touches:
canvas { touch-action: none; }
Gameplay
Hard requirements
- A clear, unambiguous ending that triggers the
reportResultcall; no open-ended or looping games. - Each Post is a self-contained experience: games are shown in any order, so each must stand alone for a first-time player.
- No in-game progression systems: no XP, leveling, or unlockables. Per-player memory (a best score, a preference) goes through userData; see Saving User Data.
- No loading screens: instantly playable. Pre-load everything inside the ZIP. Why the first seconds matter: Get Them Playing Instantly!.
- No monetization, accounts, logins, your own leaderboards, or social features.
Recommendations
- Aim for a complete, satisfying session (no fixed duration required).
- Add a brief first-play tutorial when it helps players start: keep the game immediately playable instead of gating it behind a long flow. For npm-package games, build it with the SDK overlay and gate it with
shouldShowTutorial(), which hides it once the app reports the player has played the Game. Engine games gate their own tutorial UI with the facade's call:Minit.ShouldShowTutorial()(Unity),should_show_tutorial()(Godot, Defold),Minit.shouldShowTutorial()(PlayCanvas Cloud Editor). Studio's Optimisation checklist flags a missing or ungated first-play tutorial (Unity, Godot, and Defold builds aren't checked). See Interactive Tutorials.