
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; see Interactive Tutorials.