> ## Documentation Index
> Fetch the complete documentation index at: https://docs.patch.gg/llms.txt
> Use this file to discover all available pages before exploring further.

# Release recipe

> What a release is and how players get it, sent with the release. A browser game needs none.

Every release carries a **recipe**: what it is, which games it needs, and how Patch installs and starts it. You send it with the release when you [create one](https://docs.patch.gg/api-reference/introduction.md#publishing-a-release), Patch checks it against your files and stores it with the release, and the desktop app follows it to install, launch and test your work. There's no file to keep in your project folder.

A browser game whose page is `index.html` at the top of its files needs no recipe at all: leave it out and Patch fills in the rest.

It's plain JSON in snake\_case. Its JSON Schema is at `https://patch.gg/schemas/recipe/v1.json`, and `POST /recipes/validate` checks one without creating a release.

## Examples

```json A browser game theme={null}
{}
```

```json A browser game in a folder theme={null}
{
  "components": [{ "id": "game", "file": "dist/" }],
  "launch": { "kind": "browser", "component": "game", "entry": "index.html", "aspect_ratio": "16:9" },
  "players": { "min": 1, "max": 2 },
  "test": { "checks": ["level-loads"] }
}
```

```json A mod theme={null}
{
  "games": [
    {
      "game": "hollow-knight",
      "stores": ["steam", "gog"],
      "builds": { "steam": ["15873461"] }
    }
  ],
  "components": [
    { "id": "main", "file": "plugins/", "label": "Main files" },
    { "id": "hd", "file": "textures/", "label": "HD textures", "kind": "optional" }
  ],
  "mappings": [
    { "component": "main", "to": "{profile}/BepInEx/plugins" },
    { "component": "hd", "to": "{profile}/BepInEx/plugins/Lantern/Textures" }
  ],
  "requirements": [{ "kind": "project", "project": "patch/bepinex-5", "version": "^5.4" }],
  "settings": [
    {
      "file": "{profile}/BepInEx/config/lantern.cfg",
      "format": "ini",
      "set": { "General.Enabled": true }
    }
  ],
  "credits": [
    { "files": "textures/**", "license": "CC0-1.0", "source": "https://example.com/texture-pack" }
  ]
}
```

The version, channel and changelog aren't part of the recipe: they're fields of the release itself.

## Kind

You don't set a kind. Patch reads it from the recipe's `mode` and from whether it lists a `companion` game, meaning another game it needs on the player's PC:

| `mode` | A `companion` game | Kind in the API | Players see |
| - | - | - | - |
| `browser` | No | `web_game` | Game |
| `browser` | Yes | `remix` | Remix |
| any other mode | No | `mod` | Mod |
| any other mode | Yes | `crossover_mod` | Crossover mod |

## Trust tier

You don't set this either. Patch works it out from the recipe and your files, shows it on the game page, and the API returns it as `trust_tier`. Releases that run code on the player's PC ask for their consent before the first Play.

| What the release puts on the player's PC | Trust tier | Players see |
| - | - | - |
| Nothing: a browser game runs in Patch's sandboxed game window | `sandboxed` | Runs sandboxed in patch |
| A program it starts, code files (`.dll`, `.jar`, `.exe`, `.lua`…), an archive, or anything Patch doesn't install itself (`workshop`, `manual`) | `runs_code` | Runs code on your PC |
| Anything else: data files and config | `game_files_only` | Changes game files only |

An archive counts as code until Patch's checks have looked inside it.

## Fields

Every field is optional; what you leave out takes the default shown.

| Field | Default | Meaning |
| - | - | - |
| `mode` | `browser`, or `installed` with a `host` game | `browser`: plays in Patch's game window. `installed`: into a game on the player's PC. `standalone`: a program of its own. `workshop`: a Steam Workshop item. `manual`: players install it by hand. |
| `games` | none | The games it names (below) |
| `components` | one `main` component holding every file | The parts of your files (below) |
| `mappings` | none | Where each component goes on the player's PC: `component`, `from` (`""` for all of it, `"folder/"` or one file) and `to`. Needed for `installed` and `standalone`. |
| `requirements` | none | What else it needs: `{ "kind": "loader", "loader": "bepinex-5" }` for a mod loader Patch installs and removes with your release (`bepinex-5`, `cet`, `ultimate-asi-loader`, `metamod-source`, `sourcemod`; for Minecraft `fabric`, `quilt`, `neoforge` or `forge`, with an optional `"version"`), `{ "kind": "project", "project": "owner/slug", "version": "^1.2" }` for another project on Patch (add `"optional": true` if it's only used when there), or `{ "kind": "external", "label": "…", "url": "https://…" }` for something players get themselves |
| `launch` | `browser` at `index.html`, or the game itself | `{ "kind": "browser", "component", "entry", "aspect_ratio" }`, `{ "kind": "game", "args" }`, `{ "kind": "exe", "path", "cwd", "args", "env" }` (up to 8 variables), `{ "kind": "uri", "uri" }` or `{ "kind": "none" }` |
| `settings` | none | Up to 4 config files and the values to set: `file`, `format` (`ini`, `json`, `xml` or `cfg`) and `set` |
| `test` | 1 minute a run for browser games, 5 otherwise | How Patch tests it: `minutes` per run (1 to 15), `args` for test runs, and `checks`, the names of up to 12 checks it reports itself |
| `notes` | none | `before_install` and `first_launch`: short notes players see |
| `runtime_data` | none | Folders of its own data on the player's PC, such as `{localappdata}/Lantern`, never the game's |
| `players` | none | `{ "min": 1, "max": 4 }` |
| `workshop` | none | `steam_app_id` and `file_id`, for `workshop` |
| `credits` | none | Licences of bundled work by others: `files` (a glob), `license` (an SPDX id such as `CC0-1.0`), and optionally `source` (a URL) and `author` |

### Games

| Field | Meaning |
| - | - |
| `game` | The game's slug on Patch, such as `hollow-knight` |
| `role` | `host` (the default): the game it plays in. `companion`: another game it needs on the player's PC, for its files or to run beside it. `related`: one it's only related to. |
| `version` | The game versions it works with, such as `>=1.6` |
| `stores` | The stores the game can come from: `steam`, `epic`, `gog`, `xbox`, `ea`, `ubisoft`, `battlenet` or `microsoft` |
| `builds` | Exact builds per store, such as `{ "steam": ["15873461"] }`. Leave it out to accept any build. |

An `installed` or `workshop` release has exactly one `host` game. A browser game has none.

### Components

A component names part of your files: one file, a folder ending in `/`, or `""` for every file. Every file you upload belongs to at least one component.

| Field | Meaning |
| - | - |
| `id` | Its name, such as `main` |
| `file` | `"plugins/"`, `"pack.zip"` or `""` |
| `label` | What players see, such as `HD textures` |
| `kind` | `main` (players need it, the default), `optional` (players can turn it on) or `extra` (not installed) |
| `required` | Install it even though it isn't `main` |
| `extract` | It's a single `.zip` to unpack when it's installed |

A browser game's files are uploaded as they are, never as a zip, and `launch.entry` is a path inside its component.

### Paths

Paths on the player's PC start with one of these folders:

| Folder | Is |
| - | - |
| `{profile}` | The profile folder Patch keeps for this game and set of mods |
| `{game}` | The host game's install folder |
| `{game:slug}` | Another listed game's install folder |
| `{saves}` | The game's save folder |
| `{documents}`, `{saved-games}`, `{appdata}`, `{localappdata}`, `{locallow}`, `{userprofile}` | The player's own folders |

No path can use `..`. Prefer `{profile}` wherever the game and its mod loader allow it: the game's own folder stays untouched, and uninstalling just removes the profile.

## Tests

Patch Desktop tests a browser game on its creator's PC before it goes live: it plays it as players get it and records it. If the recipe lists `test.checks`, the game reports each one while it's tested: Patch opens it with `?patch-test=1`, and the game logs one console line per check, `pass level-loads` or `fail level-loads: the map didn't load`. A run counts only when every check passed.

## Validation

Patch checks the recipe and the file list when you create a release. Each problem comes back as an [error code](https://docs.patch.gg/api-reference/introduction.md#errors) with the details:

| Code | When |
| - | - |
| `recipe_invalid` | The recipe doesn't match the schema or its rules, or doesn't match the files: a component holds nothing, a file is in no component, or the browser game's entry isn't there. `details.issues` lists each problem with its place, such as `mappings.0.to`. |
| `files_invalid` | A file's path, SHA-256 or size is wrong, or a path is listed twice |
| `version_invalid` | The release's `version` isn't semver, such as `1.2.0` |
| `unknown_host_game` | A game in `games` isn't one Patch knows |
| `unknown_project` | A project in `requirements` doesn't exist |
| `manifest_retired` | The request sent a `patch.json` manifest, which Patch no longer takes |

## Versions of the format

This is version 1 of the recipe (`schema_version: 1`). New optional fields can be added to it; anything that would break an existing recipe becomes version 2.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.