Playground — disposable chain, test WCHI, wiped without warning
Builder docs

Quickstart

The shortest honest path from nothing to a game on the Arcade — starting with whether your idea fits at all.

The shortest honest path from nothing to a game running on the Arcade.

This page is the path itself — follow it top to bottom and you will have a game running. Everything here is a command you run and a file you edit; nothing assumes an AI agent, and nothing is hidden behind one.

If you are driving an agent, the opening prompts are the literal text to paste first, and the agent skills are the same knowledge in a form it can load. Both point back here. The agent path is a convenience, not a different platform — the constraints, the commands and the submission are identical either way.

Part 0 — Will your idea fit?

Read this before anything else. It is the cheapest possible moment to find out that the Arcade is the wrong home for what you have in mind.

An Arcade game is 2 to 4 seats, React/Next only (the SDK has no supported non-React path today), and ships as a static export with no server of any kind — no API routes, no server actions, no database, no asset backend, no leaderboard service, and no accounts beyond your Xaya p/ name. All shared state is produced by a deterministic wasm judge with no floats, no clock, no network and no file access, whose state output is bounded and whose execution is fuel-capped — which caps how big a world and how long a history you can have. Input is keyboard- or tap-shaped, and every game must be playable by touch: it declares on-screen touch controls (a d-pad and/or action buttons) that the SDK mounts on touch devices, or it declares that it draws its own touch surface and takes the whole frame to draw it in — a game that declares neither is labelled desktop-only on the shelf and a player on a phone cannot start or join a match in it. There is no gamepad support and no key remapping. And a match needs two to four named, funded humans online at the same moment; there is no solo mode, no bot and no matchmaking.

Authority: arcade-xayaman/next.config.ts"A static export has NO SERVER".

If your idea does not fit, say so in Discord before you build. A persistent world, an economy or an async every-move-on-chain game is not a worse idea; it is the other architecture.

What it costs. Building and testing is free — every check in Part 2 runs offline with no chain and no funds, and the playground in Part 3 runs on a disposable fork whose wallets are pre-funded with fake money. The only real money in the whole path is the WCHI to register your own p/ name on Polygon, and you do not need one until you want to play on the real arcade.

Part 1 — What you need

  • Node 22 (20.9 is the floor, but 22 is what every gate is proven on — see What you need), Docker, git.
  • A clone of the template: git clone https://github.com/xaya/arcade-xayaman.git. /repos says what each repository is and whether you can clone it today.
  • Roughly an hour to get the template running and a match playing before you change anything. Do that first. A game you have not seen work is a game you cannot debug.

Part 2 — The offline ladder

All of this runs with no chain, no relay, no funds and no network. Get every rung green before you go near the playground.

npm ci
npm test                     # unit tests
bash blob/tests/run-tests.sh # the wasm rules, in isolation
npm run e2e                  # 12 scripted channel scenarios, no chain
npm run e2e:determinism      # the same moves must produce the same bytes
npm run selfplay             # a full match driven by script
bash blob/check-blob.sh      # the blob matches its committed sha256
npm run dev                  # single-client UI work — no chain, no wallet

npm run dev is for looking at your board and iterating on the UI. It cannot open a channel: there is no local chain, and anything involving a second player needs Part 3.

Part 3 — The playground

There is no local chain. Anything that needs a real channel — two players, a lobby, an on-chain move — needs the hosted playground at test-arcade.xaya.io. It is a disposable public test plane: its own fork, auto-accepting submissions, pre-funded wallets, wiped every Monday around 04:10 UTC and without notice in between, and it reserves nothing.

npm run dev:playground

That one committed script sets all five values the loop needs — the three proxy destinations plus NEXT_PUBLIC_POLYGON_RPC=/chain and NEXT_PUBLIC_DEV_WALLET=1. Without the last two your browser reads real Polygon while you believe you are on the fork, and you have no funded account.

The recognition test: you should see a dev-wallet picker, not a wallet-connect prompt. If you see a connect prompt, the environment did not apply — stop and fix that before going further.

Do not move those values into .env.local. Next loads that file for next build too, so they would be baked into the bundle you later submit — a game that works against the playground and is broken in production.

Then run the whole pipeline for real, on fake stakes:

  1. NEXT_PUBLIC_GAME_ID=xarc ./scripts/build-export.sh --bundle (xarc is the playground's shared move namespace, not your game key; a bundle for arcade.xaya.io is built with arcbeta — always the gameId the target plane's /arcade-config.json serves.)
  2. Upload at test-arcade.xaya.io/attach. The repository URL it asks for is recorded with the listing and never fetched, so attaching does not wait on your source being published. It auto-accepts: poll the status URL it returns until accepted (or a failed step names itself) — typically well under a minute — and the game is live on that plane both ways: bare at /g/<slug>/, and on the plane's own shelf at /play/<slug> with a card on its /games. Keep the resubmit token it gives you, out of the repository — it is the only thing that lets you re-upload the same slug after a fix.
  3. Open the game in two browser profiles, pick a different test-wallet slot in each, and play a full match. Two tabs of one profile are the same player.

Part 4 — Submit for real

Submissions on arcade.xaya.io are closed during the curated phase — /submit is hidden there and an upload answers 503. So once your dry run holds up, get in touch in #builders on the Xaya Discord with your repository, the same bytes that played, and your four registration values (slug, game type, seats, cfgSuffix). Check what you send: sha256sum dist/bundle.tar.gz blob/rules.wasm must match the bundleSha256 and rulesSha256 the playground echoed back — they are in the 201 upload response and in GET https://test-arcade.xaya.io/api/submissions/<id>, not printed on the page itself. Different hashes mean you are submitting something you never tested.

Two things are permanent once an operator accepts: your slug and your gameType. The gameType goes on chain and can never be reassigned to another game; the slug can never be reused. A rejected submission releases both — only acceptance is terminal. And there is no self-serve update path today, so a fix after acceptance costs a new slug and a new gameType.

The playground reserves nothing. It is a different chain. Success there is not a claim on anything here.

Where to go next

  • The opening prompts — the literal text to give an AI agent.
  • Agent skills — the full corpus, browsable, or a zip to unzip into .claude/skills/. Fetch it with curl, as the opening prompts do — the edge answers some non-browser HTTP clients with 403.
  • Submitting — every field on the form, and what rejects a bundle.
  • /repos — every repository this site points you at, and what your relationship to it is.