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

What you need

The repositories, access, and local tooling required to build an Arcade game.

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

RepoYour relationship to it
arcade-xayamanThe template — fork this. A complete, working game and the reference every Arcade game copies. Your game starts as a fork.
arcade-platformReference + 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-xayashipsA 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-xayatrailsA 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-dungeonchannelA 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-sumoA 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 rigThe 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

ToolVersionWhy
Dockerany recentThe 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.js20.9 floor, 22 for the gatesThe 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 3anyblob/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.
GitanyFork, commit the reproducible blob, track the vendored SDK.
A POSIX shellThe build/verify scripts are bash.

The build containers are x86_64-only. The blob builder pins wasi-sdk 24.0 for x86_64-linux by version and sha256 (blob/Dockerfile.blob-builder), and the C++ test image pins wasmtime 46.0.1 for x86_64-linux the 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. Set BUILDX_NO_DEFAULT_ATTESTATIONS=1 for 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 blob and reg admin 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 Acceptarcade-platform/games-host/src/bake.ts). The placeholder must appear both in index.html and in the script chunk that loads arcade-config.json — building with the template's build-export.sh --bundle and 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 registerGame call and the reg-move wagering block (Hosting & registration §4).

Next: Getting started.