Upload a game

One HTML file that runs on a phone. It is checked automatically and, if nothing is wrong with it, goes into the feed straight away.

We send a link instead of asking for a password. No account to create.

Writing it yourself? How to build a game has a working example to start from, the runtime reference and the safe areas.

Building it with an AI?

Paste this in first. It covers the safe areas, what the runtime gives you, and the things that simply do not work here.

Build a game for Arcade, a feed of small HTML games played on phones.

WHAT TO DELIVER
One self-contained .html file, under 2 MB. No build step, no separate files.

THE SCREEN
Portrait, phone sized. Read the real viewport and handle resize; never hard-code
dimensions.

The feed draws its own controls on top of your game. Keep anything interactive,
and anything the player has to read, out of these edges (CSS pixels):

  top 44 — the score readout
  right 68 — the like, report, liked-games and next-game buttons
  bottom 104 — the game's title and author

Do not hard-code those numbers. Read Arcade.insets, which returns
{top, right, bottom, left}, or use the CSS variables --arcade-inset-top,
--arcade-inset-right, --arcade-inset-bottom and --arcade-inset-left. They can
change, so re-layout on Arcade.on('insets', fn).

THE RUNTIME
window.Arcade already exists when your code runs. Do not add a script tag for it.

  Arcade.ready() — call once when playable; clears the loading screen
  Arcade.score(n) — current score, shown in the chrome
  Arcade.gameOver({score, won}) — a run ended
  Arcade.progress(0..1) — optional
  await Arcade.save(key, value) — persist a value
  await Arcade.load(key) — read it back, or null
  Arcade.haptic('light' | 'success') — vibrate
  Arcade.on('pause', fn) — player left: stop timers, sound and animation
  Arcade.on('resume', fn) — player came back
  Arcade.on('insets', fn) — safe area changed, re-layout
  Arcade.insets — {top, right, bottom, left}
  Arcade.registerAudio(ctx) — lets an AudioContext be suspended on pause
  Arcade.next() — ask the feed to move on

WHAT IS NOT AVAILABLE
The game runs in a sandboxed iframe with an opaque origin and no network, so
these throw or silently do nothing:

  localStorage, sessionStorage, IndexedDB — use Arcade.save and Arcade.load
  fetch, XMLHttpRequest, WebSocket — there is no network at all
  cookies and service workers
  <iframe>, <object>, <embed>
  eval and new Function
  alert, confirm, prompt, window.open — no-ops

An upload using any of these is rejected automatically, naming the line.

ASSETS
Everything inline. Draw artwork in code (canvas or CSS) rather than embedding
large images; a 2 MB budget disappears fast in base64.

Scripts may be loaded from: cdnjs.cloudflare.com, cdn.jsdelivr.net. Nothing else will load.

INPUT
Every gesture is yours: tap, hold, drag in any direction, multi-touch, tilt.
Nothing is reserved — players move between games using a button in the chrome,
not a swipe. Design for one thumb, and handle pointercancel.

WHAT MAKES A GOOD ONE
It has to be understandable in about three seconds and worth a minute. Start on
the first tap; no menus, no tutorials, no settings. One idea, done well.

QUALITY BAR
- A delta-time loop in milliseconds. Never assume a frame rate, and never mix
  per-frame and per-millisecond units — that is the single most common way these
  games end up unplayably fast or slow.
- Nothing still running after Arcade.on('pause'): no timers, no audio, no
  animation frames doing work.
- Correct on a resize and after an orientation change.
- Include <meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover,user-scalable=no">
- Call Arcade.ready() as soon as it is playable, or the feed shows a loading
  screen over your game for eight seconds and then marks it broken.

Give me the complete file, ready to upload.

What the checks look for