---
type: reference
title: Game SDK reference
summary: The complete @caputchin/game-sdk surface a game author writes against, the register function, the push-only bridge, the per-round context, and the preset types.
---

`@caputchin/game-sdk` is the contract a game author writes against: a `register` helper, a push-only `Bridge`, the per-round `GameContext`, and the TypeScript types for the manifest's preset blocks. It is published separately from the user-facing widget so games never transitively bundle the widget runtime. First-party games use this same public API; there is no private contract.

For a guided build, see [Build a marketplace game](/docs/marketplace-game-development/build-a-marketplace-game). For the manifest that declares the presets this SDK surfaces, see [The caputchin.json manifest](/docs/marketplace-game-development/the-caputchin-json-manifest).

## `register(factory)`

The single registration entry point. Pass your game factory; you do **not** pass the manifest (the server reads `caputchin.json` at index time and ships resolved presets down as the factory's context). Registering twice logs a console warning and the last write wins; there is no platform enforcement.

```ts
register(factory: GameFactory): void
```

## The game factory

```ts
type GameFactory = (
  container: HTMLElement,
  bridge: Bridge,
  ctx?: GameContext,
) => (() => void) | void
```

| Parameter | Meaning |
|---|---|
| `container` | An element inside the game's sandboxed iframe. Render here. Style is naturally scoped, the iframe is its own document. |
| `bridge` | The push-only channel to the host (see [The bridge](#the-bridge)). The game emits upward; it does not subscribe. The factory being called is the start signal. |
| `ctx` | The per-round [context](#the-context) (seed plus resolved presets). Optional in the type because the widget may run a game outside a verified session. |
| return | An optional cleanup function the widget calls if it unmounts your game. |

## The bridge [#the-bridge]

The bridge is push-only: the game reports events to the host and never listens. Its members:

| Member | Shape | Effect |
|---|---|---|
| `pass` | `pass(result: { trace: string }): void` | Signals the round was **passed**, handing the host the opaque `trace`. The server re-runs the game's [`run`](/docs/marketplace-game-development/replay-contract) under the issued seed to compute the authoritative verdict, so the game does **not** report a score here. The first call releases the held verification and locks the token; later calls are ignored. |
| `error` | `error(err: { code: string; message?: string }): void` | The game itself failed (asset load, internal exception). Surfaces an `error` event to the user. Distinct from a player losing, which is signalled by calling nothing. |
| `setSize` | `setSize(width: number, height: number): void` | Explicitly resize the iframe to fit content. Call after first paint; the widget also auto-measures the game's first child, so most games never need this. |
| `layout` | `readonly layout: 'inline' \| 'modal' \| 'fullscreen' \| null` | The resolved presentation the game runs under, or `null` when unknown. |

There is deliberately no `complete`, no `start` listener, no `unmount` method (return a cleanup function instead), and no failure signal beyond silence.

## The context [#the-context]

```ts
interface GameContext {
  seed:   Seed          | null
  locale: ResolvedLocale | null
  skin:   ResolvedSkin   | null
  config: ResolvedConfig | null
}
```

| Field | Meaning |
|---|---|
| `seed` | The per-round replay seed (a [`Seed`](/docs/marketplace-game-development/replay-contract) from the replay contract). Seed all game randomness from it. `null` when the game runs outside a verified session. |
| `locale` | The resolved language object: `_lang` (BCP-47), `_direction`, plus your flattened text keys. `null` if your manifest ships no `locales` block. |
| `skin` | The resolved skin: `_theme` plus your flattened color/asset keys, asset URLs already absolute. `_theme` is always the concrete mode the skin was resolved for, `light` or `dark` (never `any`), so a theme-agnostic preset reports the visitor's actual mode. `null` if no `skins` block. |
| `config` | The resolved configuration: your flattened typed scalars. `null` if no `configurations` block. |

Each is `null` when the corresponding manifest block is absent, so always provide a built-in fallback.

## Preset types

The SDK exports TypeScript types for authoring `caputchin.json` (and the split `.caputchin/` files) with type-checking. These mirror the [manifest](/docs/marketplace-game-development/the-caputchin-json-manifest) blocks:

| Type | Describes |
|---|---|
| `GameManifest` | The whole `caputchin.json`. Author + indexer source of truth; never read in the browser. |
| `LocalePreset` / `ResolvedLocale` | A declared locale preset / the resolved object the game receives. |
| `SkinPreset` / `ResolvedSkin` / `SkinSchemaEntry` / `SkinValueType` | Skin presets, the resolved skin, and the per-key type schema. |
| `ConfigPreset` / `ResolvedConfig` / `ConfigSchemaEntry` / `ConfigValueType` | Configuration presets, the resolved config, and the per-key type schema. |
| `LocalesFile` / `SkinsFile` / `ConfigurationsFile` | The top-level object of each `.caputchin/<axis>.json` split file. |
| `MarketplaceMetadata` / `PreferredPresentation` | The `marketplace` block and the `preferred` footprint hint. |

Author a split file with a `satisfies` import so the compiler checks it:

```ts
import type { LocalesFile } from "@caputchin/game-sdk";
export default { schema: { /* ... */ }, presets: { /* ... */ } } satisfies LocalesFile;
```

## What is intentionally absent

- No `sessionId` or platform identifiers reach the game.
- No `start` / `pause` / `resume` lifecycle hooks; the factory call is the start.
- No `maxScore` or platform score range; the verdict's score is whatever your `run` returns.

The contract is intentionally tiny so it stays stable across years of catalogue growth.

## See also

- [Build a marketplace game](/docs/marketplace-game-development/build-a-marketplace-game): the tutorial that uses this surface.
- [The replay contract](/docs/marketplace-game-development/replay-contract): the `Seed`, trace, and verdict the bridge and context refer to.
- [The caputchin.json manifest](/docs/marketplace-game-development/the-caputchin-json-manifest): declaring the presets the context resolves.
