| 1 | --- |
| 2 | title: Deployments |
| 3 | description: A project's production on every push and a live preview of every branch with a pull request, on g1t.page. Scales to zero, and billed to the workspace. |
| 4 | --- |
| 5 | |
| 6 | Deployments put your [project](/guides/projects/) on the web. They are off |
| 7 | for every project until you turn them on. Once they are on, every branch |
| 8 | with a pull request gets its own live preview, linked on the pull request, |
| 9 | and the default branch goes to production on every push. Reviewers, and the agents reviewing for you, |
| 10 | click through the change instead of reading a diff. |
| 11 | |
| 12 | Apps run on Cloudflare Workers, on `g1t.page`: |
| 13 | |
| 14 | | | Address | |
| 15 | | --- | --- | |
| 16 | | Production | `https://<project>-<workspace>.g1t.page` | |
| 17 | | Preview of the branch `fix-login` | `https://<project>-git-fix-login-<workspace>.g1t.page` | |
| 18 | |
| 19 | A preview's address follows its branch, so it stays the same for every push |
| 20 | to it. A pull request from a fork, as g1t's agents make them, is named |
| 21 | `pr-<number>` in place of the branch. A name too long for an address, or |
| 22 | one another app already has, is shortened or given a short suffix. |
| 23 | |
| 24 | A workspace whose name ends like a domain is written without that last |
| 25 | hyphen: `flagon-io` gives `https://web-flagonio.g1t.page`, not |
| 26 | `web-flagon-io.g1t.page`. Browsers read `flagon-io` in an address as a |
| 27 | copy of `flagon.io`, and warn people who visit flagon.io that the page |
| 28 | looks fake. Apps made before this moved to the new address on their own; |
| 29 | the old one redirects to it. |
| 30 | |
| 31 | When a workspace is [renamed](/guides/workspaces/#rename-a-workspace), or a |
| 32 | repository is [transferred](/guides/transferring-repositories/#deployments) |
| 33 | to another workspace or [renamed](/guides/managing-repositories/), its apps |
| 34 | are built again under addresses with the new name, and the old addresses |
| 35 | redirect to them for 90 days. A rebuild that fails is tried again an hour |
| 36 | later, then two hours after that. After three failures with the same |
| 37 | error, or after one whose commit no longer exists, it is not tried again |
| 38 | until you push or choose **Redeploy**. |
| 39 | |
| 40 | When the [default branch changes](/guides/managing-repositories/), production |
| 41 | is built again from the new default branch. An |
| 42 | [archived](/guides/managing-repositories/) repository's apps keep serving. |
| 43 | |
| 44 | Every build is also a deployment in the repository's one list of |
| 45 | deployments, beside those reported from any CI and those g1t Actions |
| 46 | jobs make, with the source `g1t_page` and the environment `production` or |
| 47 | `preview`. See [Deployments API](/guides/deployments-api/) to read them, |
| 48 | report your own, and hear of them by webhook. |
| 49 | |
| 50 | An app runs only while it answers a request. One nobody visits runs |
| 51 | nothing and costs nothing, and the next visit wakes it in milliseconds. |
| 52 | |
| 53 | Deployments are part of the [g1t plan](/guides/usage-and-billing/#the-g1t-plan), |
| 54 | and are opt-in per project. A project set to deploy on g1t, with |
| 55 | deployments off, says **Deployments are off** on its overview, with **Turn on deployments** for |
| 56 | people with the Admin [role](/guides/access-and-roles/) on its repository. Nothing builds or runs until you turn them on, and one click turns |
| 57 | them off again. |
| 58 | |
| 59 | ## Turn on deployments |
| 60 | |
| 61 | 1. **Start the g1t plan for the workspace**, if it is not on. An owner |
| 62 | opens **Settings → Billing and plans**, `g1t.sh/<workspace>/-/billing`, |
| 63 | and chooses **Start the g1t plan** on the **g1t** card. Back on |
| 64 | Billing, the card says **On the g1t plan**. The trial does not pay for |
| 65 | deployments. |
| 66 | 2. **Turn on deployments for a project.** Someone with the Admin role on |
| 67 | its repository opens the project's |
| 68 | **Settings → Deployments**, `g1t.sh/<workspace>/<project>/settings/deployments`, |
| 69 | or chooses **Deploy** on its overview, |
| 70 | and chooses **Turn on deployments**. |
| 71 | |
| 72 | Production starts building at once from the default branch. Every pull |
| 73 | request opened or pushed to from then on gets a preview. |
| 74 | |
| 75 | Deployments are for projects g1t runs. Not every project is one: a |
| 76 | library, a tool or documentation is published rather than deployed, and |
| 77 | an app may be deployed by its own pipeline somewhere else. Only a project |
| 78 | that is [an app or site deployed on g1t](/guides/projects/#what-a-project-is) |
| 79 | is asked to turn deployments on. Any other project's **Deployments** page |
| 80 | still turns them on; doing so makes it an app deployed on g1t, including |
| 81 | one that was deployed elsewhere. A project set to be a library, a tool or |
| 82 | something else cannot have deployments turned on until that setting |
| 83 | changes. |
| 84 | |
| 85 | While payments on g1t are in test mode, no real card is charged: use the |
| 86 | test card `4242 4242 4242 4242` with any future date and any code. |
| 87 | |
| 88 | ## What deploys |
| 89 | |
| 90 | g1t looks at the project's root directory and builds it the way it is meant to be built. |
| 91 | You do not configure anything for the common cases. |
| 92 | |
| 93 | | The project has | g1t | |
| 94 | | --- | --- | |
| 95 | | `wrangler.jsonc`, `wrangler.json` or `wrangler.toml` | Builds it as a **Workers project**: installs dependencies, runs `wrangler deploy --dry-run` to bundle it (which runs the config's own `build` command), and deploys the bundle with the config's static assets, `compatibility_date`, `compatibility_flags` and `vars`. | |
| 96 | | A `build` script in `package.json` | Installs dependencies, runs `npm run build`, and serves the output as a **static site**. | |
| 97 | | An `index.html` and nothing to build | Serves it as it is. | |
| 98 | |
| 99 | **Settings → Deployments** shows what g1t detected at the project's last |
| 100 | finished build (**Workers project**, **Static site** or **Plain HTML**), |
| 101 | and what running it costs. Before the first build it says **Detected at |
| 102 | the first build**. |
| 103 | |
| 104 | Dependencies are installed by the lockfile that is there: `npm ci`, |
| 105 | `pnpm install --frozen-lockfile`, `yarn install` or `bun install`, and |
| 106 | `npm install` with no lockfile. |
| 107 | |
| 108 | A static site is served from the first of these that exists after the |
| 109 | build: `dist`, `build`, `out`, `public`, `_site`, `.output/public`. Set |
| 110 | **Output directory** to choose another. |
| 111 | |
| 112 | ### Static sites |
| 113 | |
| 114 | - A site without a `404.html` is treated as a single-page app: an address |
| 115 | that matches no file serves `index.html`. With a `404.html`, that page |
| 116 | is served instead, with status 404. |
| 117 | - `_headers` and `_redirects` files in the output are honored, in |
| 118 | [Cloudflare's format](https://developers.cloudflare.com/workers/static-assets/headers/). |
| 119 | - Up to 20,000 files, and 25 MiB per file: Cloudflare's limits. |
| 120 | |
| 121 | ### Workers projects |
| 122 | |
| 123 | - Your Worker's `fetch` handler runs as written, and its static assets |
| 124 | are served under the binding name your config gives them. Cron triggers |
| 125 | (`triggers.crons`) are not scheduled, so a `scheduled` handler never |
| 126 | runs; the deployment says so in its warnings. |
| 127 | - `vars` are deployed as plain-text bindings (or JSON, for objects). Rows |
| 128 | of the project's [secrets and variables](/guides/secrets-and-variables/) |
| 129 | available to Deployments are bound too, and replace a `var` of the same |
| 130 | name: secrets as secret bindings. |
| 131 | - **Not provisioned yet:** D1, KV, R2, Durable Objects, Queues, service |
| 132 | bindings, Vectorize, Hyperdrive, Workers AI and Workflows. A project that |
| 133 | declares any of them still deploys, without them, and its deployment |
| 134 | lists each one it left out. Code that needs them should check that the |
| 135 | binding is there. |
| 136 | |
| 137 | What Deployments cannot run yet, such as long-running servers, is on |
| 138 | [What g1t can't do yet](/about/limitations/#deployments). |
| 139 | |
| 140 | ## Addresses of other projects |
| 141 | |
| 142 | A project that [depends on another](/guides/projects/#dependencies) with |
| 143 | `as: API_URL` gets that project's address as `API_URL`, in its build and in |
| 144 | its running app: |
| 145 | |
| 146 | | Building | `API_URL` is | |
| 147 | | --- | --- | |
| 148 | | Production | The other project's production. | |
| 149 | | A preview of branch `x` | The other project's preview of `x` if it is up, else its production. | |
| 150 | |
| 151 | A secret or variable of the same name wins over it. |
| 152 | |
| 153 | ### Preview stacks |
| 154 | |
| 155 | A change to an API is best seen in the apps that call it. On a pull |
| 156 | request whose preview is up, **Preview them against this change** (under |
| 157 | **Affects**) builds a preview of every project that uses this one, from its |
| 158 | own default branch, under the same branch name. Each gets this preview's |
| 159 | address through its variable. They come down with their idle days, like |
| 160 | any preview. |
| 161 | |
| 162 | ## Previews of branches |
| 163 | |
| 164 | A preview is built when a pull request is opened, when it is marked ready, |
| 165 | and on every push to it, including an agent's. Pull requests from forks, |
| 166 | which is how g1t's agents work, are built from the fork. |
| 167 | |
| 168 | The pull request shows the deployment as a check named **g1t / deploy**: |
| 169 | |
| 170 | | State | Means | |
| 171 | | --- | --- | |
| 172 | | Pending, "Building" | The build is running. The link opens its log. | |
| 173 | | Passed, "Preview is live" | The link opens the preview. | |
| 174 | | Failed, "Deployment failed" | The link opens the build log and the reason. | |
| 175 | |
| 176 | A newer push replaces a build that is still running for the same pull |
| 177 | request. Previews are marked `noindex`, so search engines leave them alone. |
| 178 | |
| 179 | The **Deployments** page lists the same failure of one app, repeated, as a |
| 180 | single row with how many times it happened and when it last did. The row |
| 181 | opens the newest of them. |
| 182 | |
| 183 | ## Production |
| 184 | |
| 185 | Each push to the default branch, which is each merge on a protected |
| 186 | branch, builds and replaces production. The **Deployments** page shows the |
| 187 | live address, the commit it runs and when it went up. |
| 188 | |
| 189 | ### The production screenshot |
| 190 | |
| 191 | When production goes live, g1t takes a screenshot of its home page, as a |
| 192 | 1280 by 800 browser window sees it, and shows it on the project's |
| 193 | [overview](/guides/projects/#the-overview). Choosing it opens the site. |
| 194 | |
| 195 | - One screenshot is taken per production deploy. g1t waits up to 12 |
| 196 | seconds for the page to settle, then takes it as it is. |
| 197 | - The screenshot is of the app's `g1t.page` address. A custom domain |
| 198 | serves the same app, so it looks the same. |
| 199 | - Until it is ready, or if it could not be taken, the overview shows a |
| 200 | plain frame with the address. A failed screenshot is tried again when |
| 201 | the overview is next opened, at most every five minutes. |
| 202 | - Only people who can read the project's repository see it, like the |
| 203 | rest of its deployments. |
| 204 | - Screenshots are not charged. |
| 205 | |
| 206 | The [checklist on the overview](/guides/projects/#get-to-production) also |
| 207 | tracks the first production deploy, a custom domain and a first preview. |
| 208 | |
| 209 | ## Custom domains |
| 210 | |
| 211 | Production can be served at a domain of your own, such as `example.com` or |
| 212 | `www.example.com`, as well as at its address on g1t.page. A domain belongs |
| 213 | to the project, not to a build: every redeploy is served on it with nothing |
| 214 | to change. |
| 215 | |
| 216 | ### Add a domain |
| 217 | |
| 218 | 1. Open the project's **Settings → Domains**, |
| 219 | `g1t.sh/<workspace>/<repo>/settings/domains`. |
| 220 | 2. Enter the domain and choose **Add domain**. Leave **Also add the www |
| 221 | (or apex) twin** checked to add both `example.com` and |
| 222 | `www.example.com` at once: the one you typed serves the app, and the |
| 223 | other redirects to it with a `308`, path and query kept. |
| 224 | 3. Add the DNS records the page lists, at whoever manages the domain's |
| 225 | DNS. Each name and value has a copy button. |
| 226 | 4. Wait. The page follows the domain from **Waiting for DNS** to |
| 227 | **Issuing certificate** to **Active** by itself; **Check now** asks |
| 228 | again at once. |
| 229 | |
| 230 | Custom domains need the workspace's g1t plan, and are $0.12 a month each |
| 231 | (their cost plus 20%), as many as you like. Adding or removing one needs |
| 232 | the Admin [role](/guides/access-and-roles/) on the project's repository. |
| 233 | |
| 234 | ### A subdomain, such as www |
| 235 | |
| 236 | Add one record: |
| 237 | |
| 238 | | Type | Name | Target | |
| 239 | | --- | --- | --- | |
| 240 | | `CNAME` | `www` | `domains.g1t.page` | |
| 241 | |
| 242 | The same goes for any subdomain, such as `app.example.com` (name `app`). |
| 243 | |
| 244 | ### The apex, such as example.com |
| 245 | |
| 246 | DNS does not allow a plain `CNAME` at the apex of a domain, so use your |
| 247 | provider's flattened form of one, pointed at `domains.g1t.page`: |
| 248 | |
| 249 | | DNS provider | Record | |
| 250 | | --- | --- | |
| 251 | | Cloudflare DNS | `CNAME` at `@` (Cloudflare flattens it) | |
| 252 | | Amazon Route 53 | Not supported by alias records to other zones; use the www pairing below | |
| 253 | | DNSimple, NS1, Namecheap, Porkbun, Gandi | `ALIAS` at `@` | |
| 254 | | DNS Made Easy, Constellix | `ANAME` at `@` | |
| 255 | |
| 256 | If your provider has no flattened `CNAME`, `ALIAS` or `ANAME`, add |
| 257 | `www.example.com` on g1t instead, and set up your provider's forwarding (or |
| 258 | any redirect) from `example.com` to `www.example.com`. |
| 259 | |
| 260 | ### Verification and certificates |
| 261 | |
| 262 | Pointing the domain at `domains.g1t.page` is what proves it is yours: once |
| 263 | the record is seen, the certificate authority checks the domain over HTTP |
| 264 | and issues a certificate, renewed by itself before it expires. Visitors are |
| 265 | always served over HTTPS, TLS 1.2 or newer. |
| 266 | |
| 267 | The page may also list a `TXT` record named `_cf-custom-hostname.<domain>`. |
| 268 | It proves ownership before traffic moves, which is useful when the domain |
| 269 | is serving a site elsewhere today: add the `TXT` first, wait for |
| 270 | **Issuing certificate** or **Active**, then change the `CNAME`. Any other |
| 271 | `TXT` records listed are for the certificate and are needed as shown. |
| 272 | |
| 273 | DNS changes can take from a few minutes to an hour to be seen. A domain |
| 274 | that stays at **Waiting for DNS** usually has a record with a typo, a |
| 275 | leftover `A` or `AAAA` record beside the new one, or (on Cloudflare DNS) a |
| 276 | `CAA` record that does not allow the certificate's authority. |
| 277 | |
| 278 | ### Remove a domain |
| 279 | |
| 280 | Choose **Remove** beside it. It stops serving the project at once, and any |
| 281 | domain redirecting to it goes too. Your DNS records are left as they are. |
| 282 | |
| 283 | ## When apps come down |
| 284 | |
| 285 | Nothing keeps running unasked. An app comes down, and stops costing |
| 286 | anything, when: |
| 287 | |
| 288 | | | | |
| 289 | | --- | --- | |
| 290 | | Its pull request is merged or closed | That preview, at once. | |
| 291 | | No one visits a preview for the project's **idle days** | That preview, at the next sweep (every 10 minutes). The default is 7 days. | |
| 292 | | You choose **Take down** on the Deployments page | That app, at once. | |
| 293 | | You turn off previews or production | All of that kind, at once. | |
| 294 | | You choose **Turn off deployments** | Every app of the project, at once, and no more builds. | |
| 295 | | The workspace's plan ends or its payment fails | Every app of the workspace, at the next sweep. | |
| 296 | | The repository is [deleted](/guides/managing-repositories/) | Every app of its projects, at once. Custom domains stay set up and serve nothing. If you restore the repository, production is built again and its domains serve it; previews come back with their next push. When it is purged, its custom domains are removed. | |
| 297 | |
| 298 | A preview that came down comes back with the next push to its pull |
| 299 | request, or **Redeploy** on the Deployments page. |
| 300 | |
| 301 | ## Who can do what |
| 302 | |
| 303 | What you can do with a project's deployments follows your |
| 304 | [role](/guides/access-and-roles/) on its repository: |
| 305 | |
| 306 | | | Needs | |
| 307 | | --- | --- | |
| 308 | | See its deployments, their build logs, previews and domains | Read | |
| 309 | | **Redeploy**, preview a stack, take an app down | Write | |
| 310 | | Turn deployments on or off, change their settings | Admin | |
| 311 | | Add, verify and remove custom domains | Admin | |
| 312 | |
| 313 | A public repository's deployments, and their build logs, can be seen by |
| 314 | anyone, signed in or not, the same as its code. Its settings and domains |
| 315 | still need Admin. A private repository's deployments are seen only by |
| 316 | people with a role on it. |
| 317 | |
| 318 | ## Settings |
| 319 | |
| 320 | Under the project's **Settings → Deployments**, |
| 321 | `g1t.sh/<workspace>/<repo>/settings/deployments`: |
| 322 | |
| 323 | | Setting | Default | | |
| 324 | | --- | --- | --- | |
| 325 | | Production | On | Deploy the default branch on every push. | |
| 326 | | Previews | On | A preview for every branch with an open pull request. | |
| 327 | | Build command | The project's own | Runs instead of `npm run build`, or before bundling a Workers project. | |
| 328 | | Output directory | Found by itself | What a static site serves. | |
| 329 | | Idle days | 7 | 1 to 90. A preview no one visits this long comes down. | |
| 330 | |
| 331 | ## Secrets and variables |
| 332 | |
| 333 | Builds and running apps read the project's |
| 334 | [secrets and variables](/guides/secrets-and-variables/) that are |
| 335 | available to Deployments, and the workspace's that reach it: |
| 336 | |
| 337 | | | Reads | |
| 338 | | --- | --- | |
| 339 | | A production build, and production | Each key's Production row, else its row for all environments. | |
| 340 | | A preview build, and the preview | Each key's Preview row, else its row for all environments. | |
| 341 | |
| 342 | The build gets them as environment variables, with secrets hidden in its |
| 343 | log. The running app gets them as bindings, `env.KEY`, put in place by g1t |
| 344 | rather than the build. Secrets reach a preview only when the pull |
| 345 | request's author has Write or higher on the repository, whether a member |
| 346 | or an [outside collaborator](/guides/access-and-roles/#outside-collaborators), |
| 347 | or it is g1t working on its own. For a pull request g1t made, whoever |
| 348 | asked for it is the one whose role counts. A preview of anyone else's pull request, such as |
| 349 | one from a fork or by someone with Read or Triage, is built and runs with |
| 350 | variables only, no secrets. |
| 351 | |
| 352 | For example, a `STRIPE_KEY` secret with a Production row holding the live |
| 353 | key and a Preview row holding the test key gives every preview the test |
| 354 | key. |
| 355 | |
| 356 | ## What it costs |
| 357 | |
| 358 | Deployments come with the |
| 359 | [g1t plan](/guides/usage-and-billing/#the-g1t-plan), $20 a month per |
| 360 | workspace with $10 of usage included. There are **no quotas**: as many |
| 361 | projects and previews as you like, and no count of builds, requests or |
| 362 | domains ever stops or pauses an app. What deployments cost g1t is metered |
| 363 | from the first unit, at Cloudflare's price plus 20%, and paid from the |
| 364 | plan's $10 of included usage first; past it, it is charged up to your |
| 365 | [spend limit](/guides/usage-and-billing/#limits). |
| 366 | |
| 367 | | | Costs g1t | You pay | |
| 368 | | --- | --- | --- | |
| 369 | | Projects, previews and the apps behind them | Next to nothing | Not charged | |
| 370 | | Builds, by the second, whether they succeed or fail | About $0.001 a minute | About $0.0012 a minute | |
| 371 | | Requests, to all of the workspace's apps | $0.30 a million | $0.36 a million | |
| 372 | | CPU time your code spends computing (waiting on the network is not counted) | $0.02 a million ms | $0.024 a million ms | |
| 373 | | Custom domains, with their certificates (a www/apex pair is two) | $0.10 a month | $0.12 a month, by the most the workspace had at once that month | |
| 374 | |
| 375 | Builds are charged when they finish. Requests, CPU time and custom domains |
| 376 | are counted through the month, so your limit and **Billing** follow them as |
| 377 | they happen, and charged once, on the first sweep after the month ends, as |
| 378 | one line: *Deployments in 2026-10: 1,240,000 requests, 3,100,000 CPU ms, 2 |
| 379 | custom domains*. |
| 380 | |
| 381 | A static site, or plain HTML, runs no code when it is visited: its files |
| 382 | are served as they are, so serving it adds no requests or CPU time. Its |
| 383 | builds are metered. A Workers project's code runs on every request, so its |
| 384 | requests and CPU time are metered too. |
| 385 | |
| 386 | An app that no one visits costs nothing. Previews still come down when |
| 387 | their pull request closes and after their idle days, to keep the list of |
| 388 | what is up short. |
| 389 | |
| 390 | The only things that stop a workspace's apps are its own spend limit |
| 391 | (apps pause with a notice, and come back once there is room) and the plan |
| 392 | ending (they come down). |
| 393 | |
| 394 | Deployments used to be a $5 plan of their own. A Deployments subscription |
| 395 | bought before keeps working until its current period ends, and is not |
| 396 | renewed. |
| 397 | |
| 398 | ### Seeing what you use |
| 399 | |
| 400 | - **Usage** shows **Deployments** with *Builds* |
| 401 | (build minutes and their cost), *Requests & CPU* and *Custom domains*, |
| 402 | in dollars, beside the rest of the workspace's usage. Requests and CPU |
| 403 | time are counted from Cloudflare's analytics every 10 minutes. |
| 404 | - The **statement** on Billing lists every build (*Building acme/web to |
| 405 | production (48 s), paid by your plan's included usage*) and every |
| 406 | month's requests, CPU time and custom domains. |
| 407 | - Each build's page shows how long it ran. |
| 408 | |
| 409 | ## Turn it off |
| 410 | |
| 411 | - **For a project:** **Turn off deployments** under its **Settings → |
| 412 | Deployments**. Every app comes down at once. Turning it on again |
| 413 | rebuilds production. |
| 414 | - **For the workspace:** when an owner ends the g1t plan on Billing, |
| 415 | deployments keep working until the date shown; then every app comes |
| 416 | down and nothing more is charged. |
| 417 | |
| 418 | Usage from the month that is under way is still charged once it ends. |
| 419 | |
| 420 | ## How it works |
| 421 | |
| 422 | 1. A pull request opens, or someone pushes. The deployments service hears |
| 423 | of it, checks that the workspace's plan is on, and reserves what the |
| 424 | build may cost (30 minutes of sandbox time) with billing. If billing |
| 425 | refuses (no paid plan, the spend limit reached, compute paused), the |
| 426 | build does not start: the deployment's status is **Skipped** with the |
| 427 | reason and what to do, and **Redeploy** shows the same reason. |
| 428 | 2. It starts a build in a sandbox of its own, the same machines that run |
| 429 | [GitHub Actions](/guides/actions/) and agents. The sandbox checks out |
| 430 | the commit with a read-only token that expires in 30 minutes. Its |
| 431 | network is restricted to the project's allowed domains, the package |
| 432 | registries, GitHub and Cloudflare's API, as |
| 433 | [workflow jobs'](/guides/actions/#what-a-job-can-reach) are, and it |
| 434 | stops at 30 minutes. |
| 435 | When it stops, what it cost is settled against what was reserved. |
| 436 | 3. The sandbox builds, then lists its files. g1t opens an upload with |
| 437 | Cloudflare for exactly those files and hands the sandbox a key that can |
| 438 | upload them and nothing else. Files Cloudflare already has are skipped. |
| 439 | 4. The sandbox sends the Worker's code to g1t, which puts the app in |
| 440 | g1t's [Workers for Platforms](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/) |
| 441 | namespace, under the name in its address. |
| 442 | 5. A request to `*.g1t.page` reaches g1t's dispatcher, which runs the app |
| 443 | by the name in the hostname. Nothing else is looked up. A request to a |
| 444 | custom domain reaches the same dispatcher through Cloudflare for SaaS; |
| 445 | it looks the hostname up once, in a key-value store kept at the edge. |
| 446 | |
| 447 | Your code never holds a Cloudflare credential, and apps are served from |
| 448 | `g1t.page`, not `g1t.sh`, so they share no cookies or origin with the site |
| 449 | you sign in to. |
| 450 | |
| 451 | ## Troubleshooting |
| 452 | |
| 453 | | You see | Do | |
| 454 | | --- | --- | |
| 455 | | "Deployments come with the g1t plan … and `<workspace>` does not have it" | An owner starts the g1t plan under Billing. | |
| 456 | | A deployment **Skipped**, saying it reached its spend limit or that new compute is paused | The build was refused before it started. Follow the link in the message: raise the spend limit, prepay, or answer the spike, on Billing. | |
| 457 | | "Stopped: unusual CPU use" | The build looked like it was mining. Contact support if it was a real build; see [abuse and mining](/guides/guardrails/#abuse-and-mining). | |
| 458 | | "403" from a host in the build log | The build's network is restricted. Add the host to the project's allowed domains under **Settings → Guardrails**. | |
| 459 | | "found nothing to serve" | Add a `build` script, an `index.html`, or a Workers config; or set **Output directory**. | |
| 460 | | "the output directory `x` does not exist after the build" | The build wrote elsewhere: check its log, then fix **Output directory**. | |
| 461 | | "`d1_databases` is not provisioned on g1t.page yet" | The app deployed without that binding. See [Workers projects](#workers-projects). | |
| 462 | | "`triggers.crons` (1 schedule) is not set up on g1t.page yet" | The app deployed, but its `scheduled` handler never runs. See [Workers projects](#workers-projects). | |
| 463 | | A preview page says "This preview is not up" | It came down (see [When apps come down](#when-apps-come-down)). Push, or choose **Redeploy**. | |
| 464 | | "Custom domains are being switched on" | Custom domains are not on for g1t.page yet. Domains you add are kept, and set up by themselves once they are. | |
| 465 | | A domain stays at **Waiting for DNS** | Check the record against the one listed, remove other `A`/`AAAA` records for the same name, then choose **Check now**. | |
| 466 | | A domain says "This domain is not set up" | It points at g1t, but no project has added it. Add it under **Settings → Domains**. | |
| 467 | | "This pull request's commit no longer exists" | The pull request's head was force-pushed over, or its branch deleted, after the build was asked for. Push to the pull request again, or close it. g1t does not try that commit again. | |
| 468 | | "The build did not finish in 45 minutes" | The build stopped reporting: a build stops at 30 minutes, and one not heard from after 45 is failed. Make the build faster, or build less for previews with **Build command**. | |
| 469 | |
| 470 | ## Running your own g1t |
| 471 | |
| 472 | Deployments need a Workers for Platforms namespace and a zone for apps: |
| 473 | |
| 474 | 1. Create the namespace: `npx wrangler dispatch-namespace create g1t-deployments`. |
| 475 | 2. Add a proxied wildcard DNS record (`*`, `AAAA`, `100::`) on the apps' |
| 476 | zone, and set the zone in `services/pages/wrangler.jsonc`. |
| 477 | 3. Create an API token with **Workers Scripts: Edit** and **Account |
| 478 | Analytics: Read**, and store it: |
| 479 | `npx wrangler secret put CLOUDFLARE_API_TOKEN` in `services/deployments`. |
| 480 | 4. Deploy `services/deployments`, `services/pages`, and the runner. |
| 481 | |
| 482 | Custom domains also need Cloudflare for SaaS on the apps' zone. Turn it on |
| 483 | under the zone's **SSL/TLS → Custom Hostnames**, give the token **SSL and |
| 484 | Certificates: Edit** on the zone, and run `scripts/setup-custom-domains.sh`: |
| 485 | it creates the `g1t-domains` KV namespace, the fallback origin's DNS record |
| 486 | (`domains`, `AAAA`, `100::`, proxied) and sets it as the fallback origin. |
| 487 | The dispatcher's `*/*` route on the zone, in `services/pages/wrangler.jsonc`, |
| 488 | is what brings custom domains' traffic to it. |
| 489 | |
| 490 | Without a card processor configured, every feature is on and nothing is |
| 491 | charged. |