Before you start, one fact shapes the whole path: submissions on
arcade.xaya.io are closed during the curated phase.
Prove your game on the playground — upload at
test-arcade.xaya.io/attach, where an upload
auto-accepts with no review and the plane wipes every Monday 04:10 UTC — then get
in touch in #builders on the Xaya Discord with
your repository and your four registration values. Wager enablement stays a
separate, manual operator action — you build and hand over artifacts, an operator
turns it on.
You build from the template; the SDK comes with it as a committed tarball, so there is no registry to sign into.
The repositories
| Repo | Your relationship to it |
|---|---|
arcade-xayaman | The template — fork this. A complete, working game and the reference every Arcade game copies. Your game starts as a fork. |
arcade-platform | Reference + SDK source. The host GSP, the judge, and @xayaarcade/sdk live here. You read it for the ABI/judge authority, and you vendor SDK updates from it (vendor-sdk.sh needs this checkout). Not forked. |
arcade-xayaships | A second worked example, read-only. A different game (a naval duel) on the same template — useful to see which choices are game-specific. Not forked. |
arcade-xayatrails | A third worked example, read-only. A 2..4-seat trail battle, and the first game built and shipped end to end by an outside builder — the closest thing to a worked answer for "what does a real submission look like". Not forked. |
arcade-dungeonchannel | A fourth worked example, read-only. A 2..4-seat hidden-information dungeon crawl: a one-byte cfgSuffix (01) and both optional additive surfaces, arcade_share_weights and arcade_ejected_mask. Not forked. |
arcade-vector-sumo | A fifth worked example, read-only. A 2..4-seat commit/reveal arena with a zero-byte channel cfg (registered with no suffix at all) and on-screen touch controls. It declares no arcade_share_weights, so its three- and four-seat wagered matches settle winner-takes-all. Not forked. |
| the fork-testing rig | The operator's deployment repository, not published — and you do not need it. It brings up a forked chain with the whole platform (GSP, relay, xayax, contracts) on top, and it is what runs the public playground. Use the playground instead of standing this up. |
You only ever fork one repo: arcade-xayaman. The rest you read, vendor from,
or hand artifacts to. (The arcade site itself is the operator's — you never touch
it; your game gets listed on it as part of registration.)
That table is the repos an Arcade builder touches. /repos indexes every repository this site points you at — what it is, and whether your relationship to it is clone, read or consume. Go there before assuming a repository you found on GitHub is the current one; several of the obvious names are frozen pre-split monorepos that predate the Arcade entirely.
AI-assisted building
The template ships Claude Code skills at .claude/skills/ in the repo:
building-channel-games (the channel protocol plus the whole Arcade path — its
ARCADE.md is the working summary of these docs) and building-persistent-games
(the other architecture — fully on-chain worlds, the libxayagame GSP, XayaX — and
the determinism and operations material both paths rest on). Open your fork with
Claude Code and they load automatically — the assistant then knows the template
layout, the blob contract, the test ladder, and the hand-over, first time. The
vendored copy is pinned by commit in .claude/skills/SKILLS-COMMIT; the same corpus
is browsable on this site at /skills, and downloadable there as a
zip if you are working outside a template fork.
Tooling
| Tool | Version | Why |
|---|---|---|
| Docker | any recent | The rules blob, the C++ test battery and the frontend image all build inside pinned containers (blob/Dockerfile.blob-builder, blob/tests/Dockerfile.testenv, docker/Dockerfile.frontend). The first blob/tests/run-tests.sh builds the test image and downloads the pinned wasmtime C API inside that build, so that one run needs network access. |
| Node.js | 20.9 floor, 22 for the gates | The template declares no engines field of its own, so nothing enforces a version: the floor comes from Next 16 (engines.node is >=20.9.0), the frontend image builds on node:20-alpine (docker/Dockerfile.frontend), and CI pins Node 22 (.github/workflows/ci.yml). 22 is what every gate is actually proven on — use it. The SDK installs from the committed tarball (no private registry); the other dependencies come from the public npm registry as usual. |
| Python 3 | any | blob/check-blob.sh's structural gate parses the wasm sections in stdlib-only Python — deliberately dependency-free, so the check runs anywhere, including where Docker is not available. |
| Git | any | Fork, commit the reproducible blob, track the vendored SDK. |
| A POSIX shell | — | The build/verify scripts are bash. |
The build containers are x86_64-only. The blob builder pins
wasi-sdk 24.0forx86_64-linuxby version and sha256 (blob/Dockerfile.blob-builder), and the C++ test image pinswasmtime 46.0.1forx86_64-linuxthe same way (blob/tests/Dockerfile.testenv) — it has to, because the determinism and fuel legs must run your blob under exactly the runtime the chain runs it under. The strip step is byte-sensitive on top of that. On an arm host (Apple Silicon and similar) run the containers under x86_64 emulation, or the reproduced hash will not match. SetBUILDX_NO_DEFAULT_ATTESTATIONS=1for image builds so BuildKit provenance does not churn image IDs.
Neither of those two images needs repository access to build: the blob builder
starts from debian:bookworm-slim and the C++ test image from the public
xaya/libxayagame image, and both pull their toolchains straight from upstream
releases, checksum-verified.
No wallet, no name, no money
Building, testing and submitting an Arcade game costs nothing. The offline ladder
(Testing) runs with no chain, no relay and no funds at all. The
public playground at test-arcade.xaya.io — its own
forked chain, auto-accepting submissions, wiped every Monday around 04:10 UTC
and without notice in between — hands you
pre-funded, pre-named dev wallets, so a real two-player match over a real
channel there needs no browser wallet, no Xaya p/ name and no WCHI;
npm run dev:playground is the committed script that points your dev server at it
(Quickstart Part 3). The upload form asks for artifacts and
facts, not a signature. So you can go clone → offline green → playground dry-run →
handed over without spending anything.
A wallet, a p/ name and WCHI are for playing on the real arcade. A name is an
ERC-721 you own; registering one costs WCHI plus POL for gas, and the fee is read
live from the chain's name policy (xaya-arcade/src/lib/chain/name-check.ts) and
shown on /account before you sign. Wagering costs whatever you stake —
with one exception worth knowing before you play for money: the first three paid
matches at a stake amount and player count nobody has played yet pay their pot to
the operator, a one-time fee that gets that stake's payouts started. Once those
three are done, that stake pays winners normally from then on, for every game.
None of that is on the build path.
What you do not do
You can build, run, and fully test a game with just the template and the tooling above. The go-live plumbing is not yours — you upload, and an Accept runs it for you — automatically on the playground, and an operator's on the arcade:
- On-chain registration — the
blobandregadmin moves (automated at Accept; the moderator signs with the arcade's admin wallet). - The path your game is served at — every game lives at
/g/<slug>/on the arcade's games origin, which on both public planes is the shell's own hostname (the operator's first-party declaration; see Overview). You build the bundle slug-agnostic against the placeholder base path/__arcade_base__, and the platform bakes the real/g/<slug>mount in (automated at Accept —arcade-platform/games-host/src/bake.ts). The placeholder must appear both inindex.htmland in the script chunk that loadsarcade-config.json— building with the template'sbuild-export.sh --bundleand its vendored SDK gives you both. You never choose, see or hardcode a path. - The shell content row — the registry entry that makes your game appear in this site (automated at Accept, via the site's runtime overlay — no rebuild).
One step stays a deliberate operator action, run after your game is live and never required for free play:
- Wager enablement — the ArcadeWager
registerGamecall and the reg-move wagering block (Hosting & registration §4).
Next: Getting started.