# Your organisation's context and starter apps

Tell every agent in your organisation how a game fits your app, once. You write
one Markdown file, `integration.md`, and publish it for your organisation. Each
agent reads it before it builds, and `gamestage create` copies it into every
new game's folder.

For what must hold in every game, publish a starter app as well: a working app
in your own stack, with your SDK version, analytics and libraries already in
it. `gamestage create --starter` starts each new game from it. See
[start games from your own app](#start-games-from-your-own-app).

```
$ gamestage org context set integration.md
Set your organisation's integration context: revision 1, set by sam@harbour-example.com on 2026-10-20.
Every member's agent reads it from now on, and `gamestage create` copies it into each new game's folder.

$ gamestage org context --save
Saved your organisation's integration context, revision 1, set by sam@harbour-example.com on 2026-10-20, to /Users/alex/games/integration.md.
```

The file is private to your organisation. Only signed-in members can read it, a
deploy never publishes it, and nobody outside your organisation can see it.

## See what your organisation has set up

Open **Organisation** in [Stage](https://gamestage.ai/stage/organisation). It
shows the integration context in force, with who set it and when, each starter
app with its versions and framework, each theme, and your organisation's
admins, so you know whom to ask for a change. Stage only reads them: an admin
changes them with the commands on this page.

## Write the file

Say what an agent needs to know to build a game that drops into your app: the
SDK version your app embeds, how sign-in reaches the game, which analytics and
consent tools you use, the libraries you prefer, and where your own code and
docs are. Plain Markdown, with code samples and links where they help.

Here is a short example for Harbour Sports, an invented company:

````markdown
# Harbour Sports: how a game fits our app

## Where games run
Games open in the Harbour app's web view on iOS and Android, and in an iframe
on harbour-example.com. Design for a 390 px wide screen first.

## Sign-in
The app is already signed in. It sends the fan's token to the game with
`postMessage({ type: "harbour:auth", token })`. Never show a sign-in screen.

## Monterosa SDK
Our app embeds Monterosa SDK v1. Use the same major version in the game.

## Analytics and consent
Use PostHog, project key in the game's settings, never in code. Consent comes
from OneTrust in the host app; read it with `window.HarbourConsent.get()`.

## Libraries
React 19 and Tailwind. No jQuery. Our components:
https://design.harbour-example.com
````

Keep secrets out of it. Every member of your organisation, and every agent
they run, reads this file. Say where a key is kept, never the key itself.

## Publish it

Only an organisation admin can publish: see
[who can change the context and starters](#who-can-change-the-context-and-starters).
Run this in the folder with the file:

```
gamestage org context set integration.md
```

Each publish is a new revision, numbered from 1. The newest revision is the one
in force, and earlier ones are kept, so you can see who changed it and when.
There is nothing to choose: to change it, edit the file and publish again.

## Read it

Any member of your organisation can read it, including an account still
waiting for approval.

```
gamestage org context                 print it
gamestage org context --save          write it to integration.md here
gamestage org context --save notes.md write it to a path of your choice
gamestage org context history         every revision, newest first
```

`gamestage create` writes `integration.md` into a new game's folder when your
organisation has one, and says so in one line. If there is already an
`integration.md` there, `create` keeps it unless you pass `--force`. Signed out
or offline, `create` skips it and makes the game as usual.

## Who can change the context and starters

An organisation admin publishes the integration context, starter apps and
themes. Everyone else in your organisation reads them. Every person who signs up owns
a workspace of their own, so owning one, or having an email address at your
organisation's domain, lets you read your organisation's files but not change
them.

### Get an organisation admin

Monterosa makes a workspace an admin for your organisation. Email us the
address each person who should publish signs in with, and we add them. Once
they are added, `org context set`, `org starter publish` and `theme publish`
work for them on their next command, with nothing to install or sign in again.

Someone whose email address is not at your organisation's domain, such as an
agency working for you, can be an admin too. We first put their workspace in
your organisation, then make it an admin.

A workspace belongs to one organisation, and is an admin for that one only.
Someone already in another organisation, through their email address or
because we put them there, cannot be made an admin of yours from the same
workspace, because they could then change neither organisation's files. They
sign in with a separate account for your organisation instead.

To stop someone publishing, ask us and we remove the admin grant. They keep
reading your organisation's files for as long as their workspace belongs to it.

| Who | Read the context, starters and themes | Change them |
| --- | --- | --- |
| Anyone whose workspace belongs to your organisation, once approved | Yes | No |
| An account waiting for approval | The context and starters from the command line, not themes or Stage | No |
| An account that was turned down | Nothing | No |
| An organisation admin | Yes | Yes, once the account is approved |
| A member of somebody else's workspace | Yes | No |
| A workspace in no organisation | Its own files only | Its own files only |

## Commands

| Command | Who can run it | What it does |
| --- | --- | --- |
| `org context` | Any member | Prints the revision in force, or one line saying there is none. |
| `org context --save [path]` | Any member | Writes it to `path`, by default `integration.md`. Writes nothing when there is none. |
| `org context set <file>` | Organisation admin | Publishes the file as a new revision. |
| `org context history` | Any member | Lists every revision: number, who set it, date and size. |

Each command takes `--json`. `org context` answers `{ "ok": true, "context": null }`
when there is none, and otherwise `context` holds the fields below.

| Field | Type | What it is |
| --- | --- | --- |
| `markdown` | string | The file, exactly as published. |
| `revision` | number | Counts up from 1 with each publish. |
| `setBy` | string | The email address of the admin who published it. |
| `setAt` | string | When, as an ISO 8601 date and time. |
| `bytes` | number | Its size in UTF-8 bytes. |

## Rules for the file

| Rule | Limit |
| --- | --- |
| Format | Markdown, saved as UTF-8 text. |
| Size | Up to 50 KB. |
| Content | Not empty, and no line that looks like a secret. |
| Visibility | Members of your organisation only. Never cached by a shared cache, never published by a deploy. |

Your organisation is decided by your workspace: by the owner's email domain,
or by Monterosa granting the workspace to your organisation. Workspaces in one
organisation share one file. A workspace in no organisation keeps its own.

## When it fails

| What you see | What happened | What to do |
| --- | --- | --- |
| `Your organisation has no integration context yet.` | Nobody has published one. | Ask an organisation admin to run `gamestage org context set integration.md`. |
| `Only an organisation admin can change Harbour Sports' integration context.` | Your workspace belongs to the organisation but is not one of its admins. | Ask Monterosa to make your workspace an admin, or send the file to an admin to publish. |
| `Only the workspace's owner can set the organisation's integration context.` | You are a member of the workspace, not its owner. | Send the file to the owner to publish. |
| `Not set. The file looks like it contains a secret` | A line looks like a private key, an API key, an AWS key, a password or a long access token. The line number is named; the value is not repeated. | Take the value out, say where it is kept instead, and publish again. Nothing was uploaded. |
| `The file is 61 KB, and the limit is 50 KB.` | The file is too long for an agent to read before it builds. | Cut it to what an agent needs, and link to longer documents. |
| `The file is not UTF-8 text.` | It was saved in another encoding, or is not text. | Save it as plain Markdown in UTF-8. |
| A message that your account is waiting for approval | You tried to publish before Monterosa approved the account. | Read it now; publish once the account is approved. |
| `Somebody else in your organisation set the integration context at the same moment.` | Two admins published at once. Both revisions are kept. | Run `gamestage org context` to read theirs, then publish yours again if it still applies. |

## How an agent uses it

The Gamestage skill tells an agent to read the context before it builds. Where
the context and the skill disagree about how the game fits your app, the
context wins. On what Gamestage requires, the skill wins: the Engine owns the
answers, every game asks fans for consent, and `gamestage verify` must pass.

The file is advice for the agent, and an agent can follow advice imperfectly.
Anything that must hold in every game belongs in the game's manifest, where
`gamestage verify` checks it.

## Start games from your own app

A starter app is a folder holding a working app in your organisation's stack.
An organisation admin publishes it once; everyone in the organisation then starts games from it,
so your SDK version, sign-in, analytics and libraries are in the code from the
first line, not left to an agent's reading.

```
$ gamestage org starter publish ./web-embed
Published web-embed@1.0.0 (vite-react) for everyone in your organisation. Every check passed.
  Files      14, 38 KB zipped
  Left out   .env.local, node_modules/

$ gamestage create --name "Cup Final Predictor" --format predict
  Started from web-embed@1.0.0, your organisation's starter app (vite-react), because it is the only one. Pass --no-starter to start without it.
  It needs building: run npm run build, then deploy dist with gamestage deploy --dir dist.
```

### Describe the starter

Put a `gamestage-starter.json` at the root of the folder:

```json
{
  "name": "web-embed",
  "version": "1.0.0",
  "description": "Harbour Sports web embed: React, PostHog, Monterosa SDK v1",
  "framework": "vite-react",
  "build": "npm run build",
  "out": "dist"
}
```

| Field | Type | Required | What it is |
| --- | --- | --- | --- |
| `name` | string | Required | 3 to 40 lowercase letters and numbers, with single hyphens between them. |
| `version` | string | Required | Three numbers, such as `1.0.0`. A published version never changes; raise it to publish again. |
| `description` | string | Required | One line for the people choosing a starter, up to 280 characters. |
| `framework` | string | Required | A word for people, such as `vite-react` or `vanilla`, up to 40 characters. |
| `build` | string | Optional | The command that builds the app. Needed when the page loads source code, such as `/src/main.tsx`. |
| `out` | string | With `build` | The folder the build writes. A game made from the starter deploys this folder. |

The folder also needs what every Gamestage game needs, because the starter is
checked against the same rules: an `index.html`, the Gamestage client, and a
`gamestage.settings.json` naming who asks for consent:

```json
{
  "consent_brand_name": "Harbour Sports",
  "privacy_policy_url": "https://harbour-example.com/privacy"
}
```

### Publish it

Only an organisation admin can publish. `org starter publish` zips the folder and
uploads it, leaving out what a deploy leaves out: `gamestage.yaml`, the
practice round, `.env` files, `integration.md`, source maps, `node_modules`,
`.git` and editor folders. It keeps `gamestage.settings.json`, `package.json`,
the lockfile and the README, which a game made from it needs.

Gamestage then checks the upload on its servers. A starter that fails any check
is refused, the answer names every check that failed, and nobody can list or
use it. Fix each one and publish again.

| Check | What passes |
| --- | --- |
| `gamestage-starter.json` | Present, valid, and naming the version being published. |
| `index.html` | At the root, or in the `out` folder. A page that loads source code needs `build` and `out`. |
| Gamestage client | The app loads `gamestage.js` or imports `@monterosa/gamestage`, and leaves the consent banner on. |
| Consent settings | `gamestage.settings.json` has `consent_brand_name` and an https `privacy_policy_url`. |
| Monterosa branding | No setting names Monterosa as the brand or links Monterosa's privacy policy. |
| No `.env` files | No file named `.env` or `.env.*` anywhere in it. |
| No secrets | No line that looks like a key, a token or a password. |
| Size and paths | Up to 25 MB zipped, 2,000 files and 100 MB unpacked. No symbolic links, and no path that leaves the folder. |

### Start a game from one

```
gamestage org starter list                          every starter, newest version first
gamestage create --starter web-embed                its newest version
gamestage create --starter web-embed@1.0.0          that exact version
gamestage create --no-starter                       the format's own page instead
```

Any member can list starters and create from them, including an account still
waiting for approval. Without `--starter`:

| Your organisation has | What `create` does |
| --- | --- |
| No starters | What it always did. |
| One starter | Uses it, and says so. |
| Several | Asks you to choose when you run it by hand. An agent, a pipeline or `--json` is told their names and stopped, with nothing written. |

`create` unpacks the starter into the game's folder, then adds what every game
gets: the game's id and manifest, `practice/round.yaml`, the Gamestage client
files the starter lacks, `integration.md`, and your organisation's sign-in and
consent defaults. It pins the starter in `gamestage.yaml`:

```yaml
experience:
  starter: web-embed@1.0.0
```

A new starter version changes no existing game. `--brand` and `--privacy-url`
still replace the starter's consent settings for this game.

### When publishing or creating fails

| What you see | What happened | What to do |
| --- | --- | --- |
| `The starter was refused, so nobody can create a game from it.` | One or more checks failed. Each is named, with what to change. | Fix each one and publish again. |
| `web-embed@1.0.0 is already published, and a published version never changes.` | That version exists. | Raise `version` in `gamestage-starter.json` and publish again. |
| `Only an organisation admin can publish Harbour Sports' starter apps.` | Your workspace belongs to the organisation but is not one of its admins. | Ask Monterosa to make your workspace an admin, or send the folder to an admin to publish. |
| `Only the workspace's owner can publish the organisation's starter apps.` | You are a member, not the owner. | Send the folder to the owner to publish. |
| `The zip is 31.2 MB, and the limit is 25 MB.` | The folder holds too much. | Leave out build output and large media. |
| `Your organisation has 2 starter apps, so create needs to know which one this game starts from.` | `create` ran without a terminal and could not ask. | Run it again with `--starter <name>` or `--no-starter`. |
| `Your organisation has no starter web-embed.` | The name or version is wrong. | Run `gamestage org starter list`. |
