---
type: how-to
title: Customize a game's skin
summary: Override a game's colors and visual assets on the Skin tab, grouped by mode (light, dark, or both); available from the Alpha plan up.
---

A game ships with a default look. On the **Skin** tab of the game's editor you can override its colors, swap its visual assets (images, and where the game uses them, audio and video), and set any non-color knobs the author exposed (a toggle, a number, a choice) so the challenge matches your brand, and the change applies to the rendered game.

Skin customization is available from the **Alpha plan up** (Alpha, Troop, Apex).

## Set colors, assets, and other knobs

Open the game on a site key's (or the troop's) **Games** page, then the **Skin** tab. The tab shows the slots the game's author exposed. Most are colors and assets, but an author can also expose a **toggle** (on/off), a **number** (often with a minimum and maximum), or a **choice** from a fixed list. Set a color with a hex or `rgb()` value; set an asset by uploading a file or pasting a URL (see below); set the other slots with the control shown. Leave a slot untouched and it keeps the game's bundled value.

## How a skin is chosen at runtime

Each preset declares the **mode** it works in: light, dark, or **any** (it reads well on both backgrounds). There is one default per mode, so the game looks right whichever mode the visitor's device prefers. A preset marked `any` is eligible to be the default for light, dark, or both. Picking one happens in two stages.

First the widget decides which skin to ask for:

1. The widget's `skin` attribute, if the page set one: an exact preset name (for example `midnight`), or the shortcut `light` / `dark`.
2. Otherwise, the visitor's system preference (`prefers-color-scheme`), which resolves to `light` or `dark`.

Then the server matches that against the presets, after merging your overrides (site key over troop over the game's bundled set). An exact preset name in the attribute wins outright. Otherwise, for the chosen mode the server takes the first preset, in declaration order, that is eligible for that mode and marked **default** (a preset is eligible when its mode is that mode or `any`); if none is marked default it takes the first eligible preset.

Because an `any` preset is eligible for both modes, you can make one skin the default everywhere, or give one mode a dedicated skin and let an `any` skin cover the other. On the Skin tab an `any` skin appears under both the light and the dark group, and you set it as the default for either or both.

On the `<caputchin-game>` element you can also pass an inline `skin` object: a JSON object written as the attribute value, for example `skin='{"primary":"#7c3aed"}'`. The widget sends it to the server as that mount's skin signal, and the server parses it and layers it on top of the resolved presets, so your inline colors and assets win over everything above (including your troop and site-key overrides). It is a property of your own markup, so it works on any plan. The checkbox `<caputchin-widget>` does not accept an inline skin; its `skin` attribute takes only `light` / `dark` or a preset name. See [our philosophy](/docs/understanding-caputchin/philosophy) for why this per-embed authoring is free.

## Assets: upload or link

An asset slot (image, audio, or video) takes either an uploaded file or a URL you paste:

- **Upload**: Caputchin stores a snapshot of the file. It is frozen, so it will not change unless you upload again.
- **Link**: you paste an `https` URL to a file you host. It is live, so replacing the file at that URL updates the game on the next load.

Because the game runs in a sandboxed frame, a linked asset only loads if its origin is allowed. Caputchin handles that for you: it allows exactly the origins your skin presets point at, and nothing else. You do not change any policy yourself.

Each asset type accepts a fixed set of formats (for example PNG, JPEG, WebP, SVG, and GIF for images). The exact formats and the color rules are in the [schema reference](/docs/references/customization-schema).

## What applies, and where

Skin overrides resolve on the server, most-specific-wins: a site-key preset beats the troop preset, which beats the game's bundled skin. You can extend a bundled preset and override only the slots you want, inheriting the rest.

## How a skin value reaches the game [#how-a-skin-value-reaches-the-game]

The server resolves your skin (your overrides merged over the bundled set) and hands the result to the **game's own code**, which draws itself with it. Colors and asset URLs arrive as text; a toggle arrives as a real `true` / `false`, a number as a real number, a choice as the chosen string. The game's author decides how each value is used, so what a slot actually changes is up to the game. You do not write any CSS for the game: it runs in a sandboxed frame you cannot style from your page.

The **widget shell** (the Caputchin chrome around the game, and the standalone checkbox) is different: its resolved skin is also exposed to your page as CSS custom properties named `--cpt-skin-<token>`, which you can read or override from your own stylesheet. That surface, and how to white-label the shell, is covered in [Style the widget with CSS](/docs/widget-customization/css-parts). Those variables are the shell's only; they do not carry a game's skin.

## See also

- [Game customization overview](/docs/game-customization/overview): register a game and manage it.
- [Configurations](/docs/game-customization/configurations) and [language](/docs/game-customization/locale): the other two axes.
- [Schema reference](/docs/references/customization-schema): color rules, asset formats, and the preset model.
- [Style the widget with CSS](/docs/widget-customization/css-parts): the shell's `--cpt-skin-*` variables and shadow parts.
