> For the complete documentation index, see [llms.txt](https://seat-airlines.gitbook.io/seat-airlines-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://seat-airlines.gitbook.io/seat-airlines-docs/for-developers/deploying.md).

# Deploying

The page on GitHub Pages, the Worker on Cloudflare, the token, and these docs on GitBook.

## The page — GitHub Pages

`.github/workflows/deploy.yml` runs on every push to `main` and on manual dispatch: it installs, runs `npm test`, builds, and publishes `dist/` to GitHub Pages. A push that changes only `docs/`, `gitbook-docs.yaml` or `.gitbook.yaml` does not redeploy the site.

1. **Turn Pages on first.** Repository → **Settings → Pages → Source: GitHub Actions**. Without it the workflow builds and then fails at the deploy step with a permissions error.
2. **Configuration** goes in repository **variables**, not secrets: **Settings → Secrets and variables → Actions → Variables**. See [Configuration](/seat-airlines-docs/for-developers/configuration.md) for why.

### The domain

`public/CNAME` holds `seat-airlines.space`, and the build copies it into `dist/`, so the custom domain survives every deploy. At the registrar:

| Type  | Name  | Value                   |
| ----- | ----- | ----------------------- |
| A     | `@`   | `185.199.108.153`       |
| A     | `@`   | `185.199.109.153`       |
| A     | `@`   | `185.199.110.153`       |
| A     | `@`   | `185.199.111.153`       |
| AAAA  | `@`   | `2606:50c0:8000::153`   |
| AAAA  | `@`   | `2606:50c0:8001::153`   |
| AAAA  | `@`   | `2606:50c0:8002::153`   |
| AAAA  | `@`   | `2606:50c0:8003::153`   |
| CNAME | `www` | `dogecoin87.github.io.` |

Then **Settings → Pages → Custom domain → `seat-airlines.space`**, wait for the DNS check, and tick **Enforce HTTPS** once it is offered.

### The wallet-free mini-game

The static build at `public/minigame/index.html` is copied into the Pages artifact at `/minigame/`, independently of the full wallet-connected site. Its hosted playable URL is:

`https://seat-airlines.space/minigame/`

It sends `radbro:game-ready`, `radbro:game-ready-request`, and `radbro:game-result` messages with a wildcard target origin. That is deliberate: the build can be embedded by either `radbro.fun` or `radbro.gg` without a domain-specific rebuild. No wallet, cookie, external asset, or network request is required by the mini-game.

### Security headers

GitHub Pages sends its own headers and ignores `public/_headers`, so none of the headers in that file are served: not the `frame-ancestors` policy that lets X frame the Player Card and keeps everyone else from framing the page, not HSTS, and not the rest. The referrer policy alone also goes out as a `<meta>` in `index.html`, because it is the only one a meta tag can carry; the others work only as real response headers. To serve them, put Cloudflare in front of the domain and copy them in with a Transform Rule. (The other way is to host the page on Cloudflare Pages, which reads `_headers` itself — a different deploy from the one above.)

1. **Put the domain on Cloudflare.** Add `seat-airlines.space` as a site, check the imported records match the table above, and change the nameservers at the registrar to the two Cloudflare gives you.
2. **Proxy the records.** In **DNS → Records**, set every `A` and `AAAA` record and the `www` `CNAME` to **Proxied** (the orange cloud). A record left on **DNS only** goes straight to GitHub, and no rule applies to it.
3. **Set encryption to Full (strict).** **SSL/TLS → Overview**. Never **Flexible**: Cloudflare would then ask GitHub over plain HTTP, **Enforce HTTPS** sends it back to HTTPS, and the site loops.
4. **Create the rule.** **Rules → Transform Rules → Modify Response Header → Create rule** (newer dashboards: **Rules → Overview → Create rule → Response Header Transform Rule**). Call it `Security headers` and choose **All incoming requests**.
5. **Set each header from `_headers`.** Under **Modify response header**, choose **Set static**, and type the header name and its value exactly as `_headers` has them; **Set new header** adds the next one. There are six: `Content-Security-Policy`, `X-Content-Type-Options`, `Strict-Transport-Security`, `Referrer-Policy`, `Permissions-Policy` and `Cross-Origin-Opener-Policy`. Do not add `X-Frame-Options`: the Player Card needs X to be able to frame the page.
6. **Deploy** the rule.

`_headers` stays the list of record: when a value changes there, change it in the rule too.

Check it from anywhere:

```bash
curl -sI https://seat-airlines.space/
curl -sI https://seat-airlines.space/terms/
```

Each reply should carry all six headers, with `server: cloudflare` and a `cf-ray` line to show it came through Cloudflare. `server: GitHub.com` means the request went round it — a record is still **DNS only**, or the nameserver change has not reached you yet.

Once the records are proxied, **Settings → Pages** may warn that the domain no longer points at GitHub; the site keeps working. If Cloudflare ever answers with **error 526**, the certificate GitHub holds for the domain has lapsed: set the records to **DNS only** until GitHub issues a new one, then proxy them again.

## The Worker — Cloudflare

`.github/workflows/worker.yml` runs on pushes to `main` that touch `worker/`. It type-checks and tests the Worker, and deploys it **only if** the repository has a `CLOUDFLARE_API_TOKEN` secret (with Workers Scripts, Workers KV Storage and Workers R2 Storage edit rights). Without one it stops after the tests and says so in the job summary — a green run does not by itself mean the Worker was deployed, so check the **Deploy** step.

By hand:

```bash
cd worker
npm install
npx wrangler deploy
curl -fsS https://<your-worker>/health
```

Worth knowing before you ship:

* **Migrations are applied by hand.** `wrangler deploy` ships code, not schema. Apply a new migration before the code that needs it:\
  `npx wrangler d1 migrations apply seat-airlines-directory --remote`
* **Set `RPC_URL`.** It is a secret: `npx wrangler secret put RPC_URL`, or run the **Set the Worker's RPC secret** workflow, which reads the repository's `RPC_URL` and `CLOUDFLARE_API_TOKEN` secrets.
* **`ALLOWED_ORIGINS` must name the site**, or every write fails in the browser with a CORS error.
* **Check `/health` after every deploy** — especially `sections` and `seated`.

## Changing the token

```bash
npm run token:update -- <new mint address>
npm run typecheck
npm run build
```

The script updates the page's committed address (`src/lib/token.ts`), the Worker's `TOKEN_MINT` (`worker/wrangler.toml`), **and every page in `docs/` that prints the old address**, so the documentation never points anyone at a retired token. Commit and push; both workflows deploy the change. If the repository has a `VITE_TOKEN_MINT` variable, set it to the same address, because it overrides the committed one.

A new mint is a new holder set: the seats and the holder count come from the new token's chain data. Visitors' browsers drop adverts and directory sessions saved for the old token. Server-side adverts, cards and messages are **not** deleted.

## These docs — GitBook

The documentation is the `docs/` folder of the repository, and `gitbook-docs.yaml` at the repository root is the contract GitBook reads: it names the site and maps that folder onto it as one space — one book, whose page tree is `docs/SUMMARY.md`. (`.gitbook.yaml` is the older, space-level version of the same pointer, kept for anything still reading it.) To connect a GitBook docs site:

1. In the site, open **Git Sync** and choose **GitHub**.
2. Install or authorise the GitBook app for `DOGECOIN87/Seat-Airlines`, and pick the branch — `main`. Leave the project directory at the repository root, where GitBook finds `gitbook-docs.yaml`.
3. For the first sync, keep the direction **GitHub → GitBook**, so GitBook imports these pages rather than overwriting them with an empty site.
4. Publish the site from GitBook.
5. The footer's **Docs on GitBook** link already opens the published site — its address is committed in `src/lib/docs.ts`. If the address ever changes, either update that constant or set the repository variable `VITE_DOCS_URL` to the new one and re-run the Pages deploy (**Actions → Deploy to GitHub Pages → Run workflow**); the variable wins over the committed address.

After that the sync runs both ways: a push to `docs/` updates GitBook, and an edit made in GitBook arrives as a commit.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://seat-airlines.gitbook.io/seat-airlines-docs/for-developers/deploying.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
