---
type: tutorial
title: Make a custom game gateable
summary: Upload a headless replay artifact for your self-hosted game so the server can re-derive the verdict, the step that lets a custom game satisfy a game gate.
---

A [self-hosted game](/docs/custom-game-development/self-hosted-game) runs and verifies as soon as you point `game-src` at it. But to use it as a [game gate](/docs/site-keys/games), where a visitor must clear it to pass, Caputchin has to be able to re-derive the result itself, not trust the browser. That is what the **replay artifact** is for. By the end of this tutorial your custom game will be gate-eligible.

This is the determinism payoff: because your game records a [trace](/docs/custom-game-development/self-hosted-game) and derives everything from the seed, the server can run a headless copy of your logic against the same seed and trace and reach the same verdict independently.

## What the replay artifact is

The artifact is a small, self-contained JavaScript bundle of just your **game logic**, with no rendering, no DOM, and no network. The server loads it into an isolated sandbox and runs it to produce a verdict from `(seed, trace)`. It is not your playable game; it is the headless judge of your playable game.

Two properties are required:

- **Self-contained.** It cannot import anything the isolate can't resolve; bundle everything in. The upload is capped at 2 MB, which is far above a typical logic bundle.
- **Deterministic and in agreement with the live game.** Given the same seed and the trace your live game emitted, it must reach the same verdict the live game claimed. If they disagree, real players get false rejections.

## 1. Register the custom game

If you have not already, register the game on the dashboard so it has an id and a place to hold the artifact. On a site key's (or the troop's) **Games** page, use the **Custom game** input in the **Add a game** panel: enter your id and click **Define**. See [custom games](/docs/game-customization/custom-games) for this step and [the schema you define](/docs/custom-game-development/dashboard-schema).

## 2. Upload the artifact

On the registered game's **Settings** tab, upload the replay bundle. It is sent as a single file; Caputchin content-hashes it (re-uploading the same bytes is a no-op) and immediately runs a **self-check**.

## 3. The self-check

The self-check runs your uploaded artifact in the replay isolate against a synthetic seed (and your committed trace sample, if you provide one) and records whether it produced a clean verdict:

- **Passes** → the install becomes gate-eligible. The **Not replayable** badge clears, and you can now turn on [require a game](/docs/site-keys/games) with this game in the pool.
- **Fails** → the artifact is still stored (so you can inspect the error), but the install stays non-gate-eligible. Fix the logic and re-upload.

A failed self-check is the system telling you the headless judge does not agree with itself or could not run; it is exactly the disagreement that would have caused false rejections in production, caught before any visitor hits it.

## 4. Turn on the gate

Once the self-check passes, the game is in the key's [gate pool](/docs/site-keys/games). Turn on **Require a game** on the key's Security page (or the troop's force-game ceiling), and Caputchin will serve your custom game, take the player's trace, and re-run your artifact server-side to decide each verification.

## Keeping the two in sync

The live game (loaded via `game-src`) and the replay artifact are two builds of the same logic. When you change anything that affects the outcome, rebuild and re-upload the artifact so the two still agree. If they drift, the self-check or production replay will start rejecting real wins. Building both from one shared logic module is the reliable way to keep them identical.

## See also

- [Build a self-hosted game](/docs/custom-game-development/self-hosted-game): producing the trace this artifact replays.
- [Games and the game gate](/docs/site-keys/games): turning the gate on and the replayability requirement.
- [Custom games](/docs/game-customization/custom-games): registering and the Not-replayable badge.
- [Dashboard schema reference](/docs/custom-game-development/dashboard-schema): the fields the game reads from its factory context.
