| 1 | --- |
| 2 | title: How g1t ships |
| 3 | description: The monorepo's layout, how each kind of unit is built, how a push to main becomes a staged deploy on g1t's own Actions, the tests that guard it, and how this section stays true. |
| 4 | --- |
| 5 | |
| 6 | import Aside from '../../../components/Aside.astro'; |
| 7 | import Diagram from '../../../components/Diagram.astro'; |
| 8 | |
| 9 | g1t is built on g1t. Its source is at |
| 10 | [g1t.sh/flagon-io/g1t](https://g1t.sh/flagon-io/g1t), every change is a |
| 11 | pull request with required checks, and its own workflows deploy it. |
| 12 | |
| 13 | ## The repository |
| 14 | |
| 15 | | Folder | Holds | |
| 16 | | --- | --- | |
| 17 | | `apps/` | What people open: `web` (the site), `api`, `status`, `sudo`, `docs`, and the `desktop` (Tauri) and `mobile` (Expo) apps | |
| 18 | | `services/` | The services, one folder each, with their `wrangler.jsonc` and `migrations` | |
| 19 | | `crates/` | Shared Rust: `contracts`, `kit`, `rules`, `scan`, `secrets`, `blobstore`, `actions`, the `runner` binary and the `g1t` CLI | |
| 20 | | `packages/` | Shared TypeScript: `contracts` and `theme` (the design tokens) | |
| 21 | | `deploy/` | `stack.jsonc`, the inventory; `self-host`, the Docker Compose installation; `runner` and `sandbox`, the self-hosted runner's images | |
| 22 | | `scripts/` | `deploy.mjs` and its helpers, releases, operations | |
| 23 | | `plugins/` | The [Claude Code plugin](/guides/claude-code-plugin/), and setup for other coding agents | |
| 24 | | `.g1t/workflows/` | CI, deploys and releases, run by g1t Actions | |
| 25 | | `conformance/` | Checks that a job's environment matches what workflows expect | |
| 26 | |
| 27 | ## Building |
| 28 | |
| 29 | `deploy/stack.jsonc` gives each unit a kind, and each kind builds its own |
| 30 | way: |
| 31 | |
| 32 | | Kind | Built by | Units | |
| 33 | | --- | --- | --- | |
| 34 | | `rust-worker` | `scripts/build-rust-worker.mjs`: `worker-build` to WebAssembly, then `wasm-opt` | The Rust services and `apps/api` | |
| 35 | | `ts-worker` | Wrangler's bundler | The TypeScript services | |
| 36 | | `react-router` | `vite build`, then Wrangler | `apps/web`, `apps/sudo` | |
| 37 | | `astro` | `astro build` | `apps/docs` | |
| 38 | |
| 39 | The runner's image is built in two layers: a large base with every |
| 40 | toolchain, rebuilt only when its folder changes and recorded in |
| 41 | `services/runner/base.json`, and a thin layer on top with the static |
| 42 | `g1t-runner` binary. |
| 43 | |
| 44 | ## Deploying |
| 45 | |
| 46 | <Diagram name="deploy-stages" /> |
| 47 | |
| 48 | A push to `main` starts `.g1t/workflows/deploy.yml`, one run at a time, |
| 49 | never cancelled: |
| 50 | |
| 51 | 1. **Check and plan.** The manifest is checked against every config and |
| 52 | `npm run test:deploy` runs. Beside it, `scripts/deploy.mjs plan` works |
| 53 | out which units changed since the commit each one is running. |
| 54 | 2. **Migrations.** Every pending D1 migration, before any code. |
| 55 | 3. **Core, edge, front.** The units in each stage deploy in parallel; a |
| 56 | stage starts only when the one before succeeded. A unit binds only to |
| 57 | units in its own stage or an earlier one, which a test checks, so new |
| 58 | code never calls a service that has not shipped yet. |
| 59 | 4. **Smoke.** `scripts/ops/smoke.mjs` checks that sign-in and sign-up still |
| 60 | work, without making an account. |
| 61 | |
| 62 | Each run is one `production` deployment, shown on the commit as the |
| 63 | `deploy / production` status. Only units whose inputs changed are |
| 64 | deployed: their folder, or a crate or package they are built from, which |
| 65 | `deploy.mjs` reads from Cargo's and npm's workspace metadata. |
| 66 | [Deploy g1t to Cloudflare](/guides/deploy-to-cloudflare/) covers the |
| 67 | tool, rollbacks and a first deploy. |
| 68 | |
| 69 | ## Tests that guard the architecture |
| 70 | |
| 71 | Some of what this section describes is enforced by tests, so a change that |
| 72 | breaks it fails CI: |
| 73 | |
| 74 | | Test | Fails when | |
| 75 | | --- | --- | |
| 76 | | `npm run test:deploy` | A unit is missing from `stack.jsonc`, a binding crosses stages the wrong way, a unit is missing from [How a self-hosted g1t runs](/guides/self-hosting-architecture/), or [Services and contracts](/architecture/services/) disagrees with a `wrangler.jsonc` | |
| 77 | | `cargo test -p g1t-contracts` | The Rust and TypeScript access rules or scopes differ | |
| 78 | | `cargo test -p g1t-api openapi` | The docs' copy of the OpenAPI document is out of date | |
| 79 | | `app/lib/front-door-limits.test.ts` in `apps/web` | A `wrangler.jsonc` and `packages/contracts/src/rate-limits.ts` disagree | |
| 80 | | `npm test` in `apps/docs` | A diagram's arrow names a box that does not exist, two boxes overlap, or a label does not fit its box | |
| 81 | |
| 82 | CI (`.g1t/workflows/ci.yml`) runs the Rust tests, the TypeScript checks and |
| 83 | tests, and builds the site, sudo and these docs on every pull request. |
| 84 | |
| 85 | ## Keeping this section true |
| 86 | |
| 87 | These pages describe the code on `main`. When you change how g1t is put |
| 88 | together, change them in the same pull request: |
| 89 | |
| 90 | | If you change | Update | |
| 91 | | --- | --- | |
| 92 | | A service's bindings, storage or job | Its row in [Services and contracts](/architecture/services/#every-unit) and [Data and storage](/architecture/data/) | |
| 93 | | A request's path, a limit or a deadline | [How a request is served](/architecture/requests/) | |
| 94 | | An event type or a route to a subscriber | [Events](/architecture/events/) | |
| 95 | | The push, fetch or merge path | [Git](/architecture/git/) and [Work and the merge queue](/architecture/work/) | |
| 96 | | Sandboxes, runners or egress | [Actions, runners and sandboxes](/architecture/compute/) | |
| 97 | | A new dependency on a Cloudflare product | Its port in [Data and storage](/architecture/data/#ports-and-adapters) | |
| 98 | |
| 99 | Diagrams are data, in `apps/docs/src/diagrams/architecture.ts`. Change the |
| 100 | spec, and both the picture and the page's Markdown copy change with it. |
| 101 | |
| 102 | <Aside title="Run it yourself"> |
| 103 | `docker compose -f deploy/self-host/docker-compose.yml up --build` |
| 104 | builds every unit from source and starts the site on port 8787 and the |
| 105 | API on 8789. [Run g1t yourself](/guides/self-hosting/) has the rest. |
| 106 | </Aside> |