# Publishing to hustle.themonochrom.com

The deploy is automated. `.github/workflows/publish.yml` runs on every push to
`main` and calls `.github/scripts/publish.sh`, which:

1. verifies the Cloudflare API token,
2. resolves the account id from the token,
3. creates the Pages project `hustle` if it does not exist,
4. uploads the committed tree with `wrangler pages deploy`,
5. attaches `hustle.themonochrom.com` as a custom domain,
6. creates the proxied `CNAME` in the `themonochrom.com` zone if Pages did not,
7. polls `https://hustle.themonochrom.com/` and reports the status code.

Every step is idempotent, so re-running is safe.

## The one manual step

The workflow needs a Cloudflare API token. There is no way around this: Cloudflare
requires authentication for writes, and no credential exists in the repository or
in the Claude Code container.

1. https://dash.cloudflare.com/profile/api-tokens -> **Create Token** ->
   **Create Custom Token**
2. Permissions:
   - **Account** / **Cloudflare Pages** / **Edit**
   - **Zone** / **DNS** / **Edit**
3. Zone Resources: **Include** / **Specific zone** / `themonochrom.com`
4. Create it, copy the value, and paste it at
   https://github.com/themonochrom/hustle/settings/secrets/actions
   as a repository secret named `CLOUDFLARE_API_TOKEN`.

Then run the workflow: **Actions** -> **Publish to hustle.themonochrom.com** ->
**Run workflow**. It takes about two minutes, plus certificate issuance on the
first run.

Optional second secret: `CLOUDFLARE_ACCOUNT_ID`. Only needed if the token can see
more than one Cloudflare account, in which case the run fails with a message
naming them.

## Why this runs in GitHub Actions and not in the Claude Code container

The container's egress gateway rejects Cloudflare:

```
$ curl https://api.cloudflare.com/client/v4/user/tokens/verify
Host not in allowlist: api.cloudflare.com.
Add this host to your network egress settings to allow access.
```

`dash.cloudflare.com` is refused the same way, through curl and through headless
Chromium alike. A GitHub Actions runner has open outbound internet, so the deploy
lives there instead. Adding `api.cloudflare.com` to the environment's egress
allowlist would also work, but it is not required.

## Route check

The `themonochrom-router` Worker on this account serves `themonochrom.com`,
`www.themonochrom.com` and `jayor.app`, matching on exact hostnames and on
`/jayor/*`, `/compras/*`, `/mercado/*` and `/publico/*` paths. It declares no
wildcard such as `*themonochrom.com/*`, so it does not intercept
`hustle.themonochrom.com`. Nothing in the router needs to change.

## What is served

- `index.html` landing page: five businesses, three design options each
- `sites.html` index of all 15 sites
- `rank-N-*/yard-sign|the-ledger|the-console/` the 15 sites
- `scorecard/` the weighted scorecard
- `rollout-plan.html`, `build-tracker.html`, `docs/`

All prebuilt static HTML, 54 files, 2.2 MB, no build step and no server code.
Well inside the Pages free tier.
