Skip to content

Commit bba6320

Browse files
authored
Merge pull request #5 from owid/document-cf-infra
📜 Document Cloudflare Pages infrastructure
2 parents 4c8a764 + 84b18b8 commit bba6320

2 files changed

Lines changed: 128 additions & 49 deletions

File tree

INFRASTRUCTURE.md

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# Documentation infrastructure
2+
3+
This repo is the **umbrella** of OWID's technical documentation. Its content is small (a landing page plus links into the subprojects). What makes it special is that it owns the custom domain and acts as a **router** in front of subproject Pages projects, so one URL transparently serves docs from multiple GitHub repos.
4+
5+
```
6+
docs-cf.owid.io (later: docs.owid.io)
7+
8+
9+
┌──────────────────────────────┐
10+
│ Cloudflare Pages project │
11+
│ owid-docs (this repo) │
12+
│ ───────────────────────── │
13+
│ _worker.js (router) │
14+
└──────────────┬───────────────┘
15+
16+
┌──────────────────┼──────────────────────────┐
17+
│ │ │
18+
▼ ▼ ▼
19+
/projects/etl/* /projects/owid-grapher-py/* everything else
20+
│ │ │
21+
▼ ▼ ▼
22+
owid-etl-docs owid-grapher-py-docs this repo's
23+
.pages.dev .pages.dev static assets
24+
(owid/etl) (owid/owid-grapher-py)
25+
```
26+
27+
## Repos involved
28+
29+
| Repo | Pages project | Path prefix |
30+
|---|---|---|
31+
| `owid/owid-docs` (this) | `owid-docs` | `/` (umbrella + router) |
32+
| `owid/etl` | `owid-etl-docs` | `/projects/etl/` |
33+
| `owid/owid-grapher-py` | `owid-grapher-py-docs` | `/projects/owid-grapher-py/` |
34+
35+
Each subproject repo owns:
36+
- a `.github/workflows/deploy-docs-cf.yml` that builds the docs and uploads to its Pages project via `wrangler pages deploy`
37+
- a sed-override of `site_url` in CI so the canonical/sitemap URLs reflect the production path on `docs-cf.owid.io/projects/<short>/`
38+
39+
Per-PR previews still work on each project's own `*.pages.dev` URL — the umbrella router is only invoked for traffic to the custom domain.
40+
41+
## `_worker.js` — the router
42+
43+
Lives at repo root, copied into `site/` by the deploy workflow so CF Pages picks it up at the deployment root. When present, it intercepts every request to the Pages project.
44+
45+
Responsibilities, in order:
46+
47+
1. **Legacy URL rewrite** — strip the `/en/latest` segment baked into old ReadTheDocs links and 301 to the canonical path.
48+
2. **Subproject routing** — match a `SUBPROJECTS` prefix, `fetch()` the same path on the target Pages project, and stream the response back.
49+
3. **Fallback**`env.ASSETS.fetch(request)` serves this repo's own static assets (umbrella landing page, CSS, etc.).
50+
51+
To add a new subproject, append one line to the `SUBPROJECTS` map.
52+
53+
## Adding a new subproject
54+
55+
Concrete example: a hypothetical `owid/foo-docs` repo serving its docs at `docs.owid.io/projects/foo/`.
56+
57+
1. **Create the CF Pages project** (use CLI — the dashboard's "Upload static files" flow now creates a Worker, not a Pages project):
58+
59+
```bash
60+
npx wrangler pages project create foo-docs --production-branch=master
61+
```
62+
63+
2. **Add a workflow** in `owid/foo` mirroring [`.github/workflows/deploy-docs-cf.yml`](./.github/workflows/deploy-docs-cf.yml) from this repo or from `owid/etl`. Two things to adjust:
64+
- sed-replace `site_url` to `https://docs-cf.owid.io/projects/foo/` (later `docs.owid.io/projects/foo/`).
65+
- Stage the build into `staging/projects/foo/` before `wrangler pages deploy`.
66+
67+
3. **Add repo secrets** in `owid/foo`: `CLOUDFLARE_API_TOKEN`, `CLOUDFLARE_ACCOUNT_ID` (same values used by the other repos).
68+
69+
4. **Open a PR on this repo** appending the new prefix to `_worker.js`:
70+
71+
```js
72+
const SUBPROJECTS = {
73+
"/projects/etl/": "https://owid-etl-docs.pages.dev",
74+
"/projects/owid-grapher-py/": "https://owid-grapher-py-docs.pages.dev",
75+
"/projects/foo/": "https://foo-docs.pages.dev", // new
76+
};
77+
```
78+
79+
5. **Merge order**`owid/foo` PR first (so the target Pages project gets its first production deploy), then this repo's worker PR. Reverse order is safe but `/projects/foo/*` will 404 in the interim.
80+
81+
## Common operations
82+
83+
### Cache purge (after risky changes)
84+
85+
CF aggressively caches both static assets and worker responses (including 301s). If something looks stale after a deploy:
86+
87+
CF dashboard → **owid.io zone** → Caching → Configuration → Purge Cache → Custom Purge → enter the specific URL(s) → Purge.
88+
89+
### Swapping the custom domain
90+
91+
Currently `docs-cf.owid.io` is bound to the `owid-docs` Pages project. To re-attach to another project (e.g., during emergency rollback), detach from the source first, wait ~30 s, then attach to the target.
92+
93+
### Production branch
94+
95+
Production deploys on a Pages project are only those uploaded with `--branch=<production-branch>`. The production branch is set when creating the project (`--production-branch=master|main`); changing it later via the dashboard requires re-deploying because CF does not auto-promote the latest deploy on the new branch.
96+
97+
### Required repo secrets
98+
99+
Each subproject repo + this one needs:
100+
101+
- `CLOUDFLARE_API_TOKEN` — custom token scoped to `Account › Cloudflare Pages › Edit` + `User › User Details › Read`.
102+
- `CLOUDFLARE_ACCOUNT_ID` — visible in the CF dashboard URL.
103+
104+
One token + account ID pair works for all repos.
105+
106+
## Related deployments (unchanged today)
107+
108+
- **ReadTheDocs** — still serves `https://docs.owid.io/` and the subprojects. Builds untouched. Will be decommissioned once the CF mirror has been validated and `docs.owid.io` DNS is repointed.
109+
- **GitHub Pages**`.github/workflows/docs.yml` in this repo still publishes a copy. No active consumer; can be removed after the cut-over.

README.md

Lines changed: 19 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,32 @@
11
# OWID Documentation
22

3-
**Work in Progress**
3+
Umbrella site for OWID's technical documentation.
44

5-
Technical documentation for Our World in Data projects.
5+
Production URL during the parallel-hosting phase: **https://docs-cf.owid.io/**.
6+
The current production URL on ReadTheDocs is unchanged: **https://docs.owid.io/**.
67

7-
## Development
8+
## What's in this repo
89

9-
This project uses [uv](https://docs.astral.sh/uv/) for Python dependency management.
10+
| | |
11+
|---|---|
12+
| `docs/` | Source markdown for the umbrella landing page + links into subprojects |
13+
| `zensical.toml` | Site config (Zensical / Material) |
14+
| `_worker.js` | Cloudflare Pages worker — proxies subproject paths to other Pages projects (`/projects/etl/*`, `/projects/owid-grapher-py/*`, …) |
15+
| `.github/workflows/deploy-docs-cf.yml` | Builds + deploys this site to Cloudflare Pages on every push to `main` |
16+
| `.github/workflows/docs.yml` | Legacy GitHub Pages deploy (will be removed after the RtD cut-over) |
17+
| `.readthedocs.yml` | RtD build config (unchanged during the transition) |
18+
| `INFRASTRUCTURE.md` | How the CF deployment fits together + how to add a new subproject |
1019

11-
### Setup
20+
## Local development
1221

1322
```bash
14-
# Install dependencies
1523
uv sync
16-
17-
# Serve documentation locally (when Zensical is ready)
18-
uv run zensical serve
19-
20-
# Build documentation
21-
uv run zensical build
24+
uv run zensical serve # http://localhost:8000
25+
uv run zensical build --clean # output: site/
2226
```
2327

24-
### Current Status
25-
26-
- **Build System**: MkDocs with Material theme (currently active)
27-
- **Migration Target**: Zensical (Material team's new static site generator)
28-
- **Zensical Status**: Alpha (expected stable release early 2026)
29-
30-
### Configuration Files
31-
32-
- `mkdocs.yml` - Current MkDocs configuration (actively used)
33-
- `zensical.toml` - Future Zensical configuration (ready for migration)
34-
- `pyproject.toml` - Python project dependencies
35-
36-
### Migration to Zensical
37-
38-
Zensical is the successor to Material for MkDocs, built by the same team. Key features:
39-
40-
- **5x faster** rebuild times
41-
- **Backward compatible** - can read existing `mkdocs.yml`
42-
- **Modern design** with new Disco search engine
43-
- **Rust-powered** Markdown parser (coming 2026)
44-
45-
#### When to Migrate
46-
47-
- Monitor [Zensical roadmap](https://zensical.org/about/roadmap/)
48-
- Wait for stable release (expected early 2026)
49-
- Test with `zensical.toml` when CLI is available
50-
- Material for MkDocs will be supported for at least 12 months
51-
52-
#### Migration Steps (when ready)
53-
54-
1. Ensure Zensical ≥0.1.0 is installed
55-
2. Test build: `uv run zensical build`
56-
3. Compare output with MkDocs build
57-
4. Update CI/CD to use Zensical
58-
5. Optionally switch to `zensical.toml` for new features
28+
## Deployment
5929

60-
## Documentation
30+
Pushes to `main` deploy to the [`owid-docs`](https://dash.cloudflare.com/?to=/:account/pages/view/owid-docs) Cloudflare Pages project. PRs get per-PR preview URLs at `<branch>.owid-docs.pages.dev`.
6131

62-
Visit the documentation at: https://docs.owid.io/
32+
For the full picture — adding a new subproject, swapping the custom domain, cache-purge ops — see [`INFRASTRUCTURE.md`](./INFRASTRUCTURE.md).

0 commit comments

Comments
 (0)