# Submit your game to LiveArena

**Use `arena preview` and `arena submit`.** `arena-submit` and the local web uploader write a local file store. Their `[review]` status never reaches the hosted staff queue.

Run from the repository or extracted builder root with Node.js 22+ and npm.

## First milestone: a hosted watch link

Start with a small working game and verify the whole path before investing in a custom presentation:

```sh
npm run arena -- new games/my-game --genre kart-racer
npm run arena -- preview games/my-game
```

The starter includes scene geometry, public actor animation, director moments, sound cues, and a verified spectator replay adapter. The preview command builds your package, certifies the exact upload snapshot, runs trial matches, registers a persistent identity, uploads an immutable ZIP, and prints a private watch link. It does not create a submission or ask the owner to confirm.

If you already have an identity or project, supply them on the first run:

```sh
npm run arena -- preview games/my-game --key "$HOME/.config/livearena/muse-key.json" --project YOUR_PROJECT_UUID
```

A queued build is not ready to watch. Run `npm run arena -- status games/my-game` to see hosted validation and preview readiness for that exact build. The watch link follows the project's latest ready build: check its displayed version, particularly while an update is still validating. API deployments without the build-status endpoint report unknown validation status and check preview readiness separately.

## Submit and hand off

Review the full match against the [presentation requirements](build-a-game.md#presentation-is-part-of-the-game), then submit:

```sh
npm run arena -- submit games/my-game --owner-email you@example.com
npm run arena -- status games/my-game
```

An unchanged package reuses the preview build. Use `--listing listing.json` for a custom title, description, and credits. The default listing uses the project title and game description. Submission checks host admission (`defineHostedGame`, real-time, matching publisher) before creating a hosted review record.

The command prints the hosted project/build/submission IDs, private receipt path, status, and pending actions. **A hosted submission ID is the receipt; local certification alone is not.** Arena queues an email to the supplied owner address. The human owner opens that email or the private completion URL, signs in with the same verified email address, and explicitly confirms ownership and release authorization. Supplying an address does not accept terms. The exact expiry comes from hosted status; the normal confirmation window is seven days. Never post completion links publicly. Owner confirmation, hosted validation, staff review, and publication remain distinct steps.

`status` includes notification states: `queued` or `sending` means pending, `sent` means accepted by the email provider, and `attention` needs operator help. Delivery events are reported separately; a sent email is not proof it reached the inbox. After successful publication, Arena emails the confirmed owner the public game link. Approval alone does not send that announcement.

To request another confirmation email without uploading again:

```sh
npm run arena -- submit games/my-game --resend-confirmation
```

Resends preserve the original address and expiry. An already pending invitation is reused; limits are one request per minute and five invitations per recipient per day. The private receipt is required. An expired link requires a new submission.

## Resume safely

If a request fails or its response is lost:

```sh
npm run arena -- resume games/my-game
```

Resume uses saved IDs, tokens, listing, and ZIP bytes. It does not rebuild from your edited source or create duplicate projects/submissions. A pending operation must be resumed before starting another preview or submission. `status` reads hosted records without creating anything. Commands exit nonzero on errors; `--json` produces a machine-readable success result for agents.

## One identity and a private receipt

The default key is `~/.config/livearena/muse-key.json`, created once with mode 0600. Private receipts and immutable snapshots live under `~/.config/livearena/receipts/`, outside the game directory. Back up both the key and receipt directory. Resume requires the same game-directory path; if moving machines or directories, keep the saved IDs and use the low-level client rather than accidentally creating another project.

Use `--state-dir PATH` for an isolated test identity/receipt store and `--api-url HTTPS_URL` for staging. A receipt stays bound to its original service, project, and key. A missing saved key is an error, never an invitation to generate another identity.

The ZIP contains only `package.json`, built `dist/`, and optional `assets/`. Source maps, root secrets, and node_modules are excluded; symlinks and recognizable private-key files in the packaged directories are rejected. Inspect the saved archive before sharing if your build writes other sensitive content. The hosted limit remains 1 MiB compressed. Include required runtime assets in `assets/` or `dist/`.

The packager adds only the **public** publisher key to the snapshot's `package.json`. Your game manifest should read `publisher` from that file (as the starter does). Your original package is not rewritten. The submitted game/package versions must match.

## Update a game

Reuse the directory and receipt. Bump the game and package versions, edit, and run preview again. Changed bytes without a version bump are rejected. Then submit the new build and have the owner confirm again. The previous ZIP and submission remain immutable. Pass the same `--listing` on repeated submit commands; changing a frozen listing requires a new version. Expired confirmation currently requires a new submission; with this CLI, upload a new version to create one.

## Low-level client and local operator tools

The included `packages/entry/starter-kit/creator.mjs` remains available for explicit register/project/upload/preview/submit/status operations and migration of existing projects. Its individual create commands generate fresh IDs; use the resumable flow above for routine work.

`arena-submit` and the local web uploader still serve the separate file-backed operator pipeline. They never put a submission in the hosted creator staff queue. See [local submission rehearsal](local-submission-rehearsal.md).
