Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 47 additions & 33 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,34 @@ release from it and run the workflow against the new tag.

## Versioning the docs

Docs are versioned at the minor level, each version on its own subdomain, served
by a single Vercel project with one branch domain per build:

- `docs.modelplane.ai` — the canonical apex. Its home page redirects to the
latest release, so a reader who types the bare domain lands on the latest docs.
- `vX-Y.docs.modelplane.ai` — each minor release (`v0-1`, `v0-2`, …), built from
its `release-X.Y` branch.
- `main.docs.modelplane.ai` — the dev docs, built from `main`, so unreleased docs
stay browsable.

Both `main.docs` and the apex are built from `main`; what tells them apart is the
baseURL. The apex build redirects because its baseURL isn't `main`'s own subdomain
(`docs/themes/geekboot/layouts/index.html`). The redirect target is the latest
release's URL, looked up in `docs/data/versions.yaml` by `latest` in
`docs/hugo.toml`.
Docs are versioned at the minor level, each version on its own subdomain. Two
Vercel projects serve them, and each domain serves its build's content directly —
nothing redirects:

- **dev project** (`main` branch) — serves `main.docs.modelplane.ai`, the
unreleased docs, so work in progress stays browsable.
- **release project** (latest `release-X.Y` branch) — serves both
`docs.modelplane.ai` (the canonical apex, always the latest release) and that
release's permanent `vX-Y.docs.modelplane.ai` subdomain.

Older releases keep their own project on their `vX-Y.docs.modelplane.ai`
subdomain. There is no apex redirect: `docs.modelplane.ai` *is* the latest
release's build, so a reader on the bare domain gets the latest docs with the URL
unchanged. What a build serves is decided entirely by its Vercel project and
baseURL, never by the home page (`docs/themes/geekboot/layouts/index.html`).

Each project's baseURL:
- dev project → `HUGO_BASEURL = https://main.docs.modelplane.ai/` (scoped to `main`).
- release project → `docs.modelplane.ai` (leave `HUGO_BASEURL` unset in
production so the build uses the baked `https://docs.modelplane.ai/` from
`nix/docs.nix`). The `vX-Y` subdomain aliases the same build.
- PR previews → root-relative `HUGO_BASEURL = /`, so assets resolve against the
preview host.
- local (`hugo server`) → `localhost` from hugo.toml's `baseURL = "/"`.

`docs/data/versions.yaml` is the single list of every version and its URL. It
drives the version dropdown and the apex redirect, and must be identical on every
branch — `main` and all release branches — so each build offers the same switcher.
drives the version dropdown and must be identical on every branch — `main` and all
release branches — so each build offers the same switcher.

One-time DNS setup (already done): a wildcard CNAME `*.docs.modelplane.ai →
cname.vercel-dns.com` covers `main.docs` and every release subdomain. No new DNS
Expand All @@ -59,26 +68,31 @@ To publish docs for a new minor release (e.g. `v0.1.0`):
- version: "0.1"
url: "https://v0-1.docs.modelplane.ai"
```
On `main`, also set `latest = "0.1"` in `docs/hugo.toml` so the apex redirects
to the new release.
On `main`, also set `latest = "0.1"` in `docs/hugo.toml` so the version
dropdown and the "not the latest release" banners point at the new release.

3. In the Vercel dashboard, open the `modelplane-docs` project and add a branch
domain for the release:
- Go to Settings → Domains, add `v0-1.docs.modelplane.ai`, and assign it
to the `release-0.1` branch.
- Add a Production environment variable scoped to the `release-0.1` branch:
`HUGO_BASEURL` = `https://v0-1.docs.modelplane.ai/`.
- Trigger a redeployment of `release-0.1` and confirm the subdomain serves.
3. In the Vercel dashboard, create the release project for `release-0.1` (or
reuse the existing one) and, under Settings → Domains, assign it both
`docs.modelplane.ai` (the apex) and `v0-1.docs.modelplane.ai`. Leave
`HUGO_BASEURL` unset in Production so the build bakes `https://docs.modelplane.ai/`.
Trigger a redeployment and confirm both domains serve.

4. Merge the changes. The apex now redirects to the new release, and the version
dropdown on every build links to it.
4. Merge the changes. The apex now serves the new release directly, and the
version dropdown on every build links to it.

The `main.docs.modelplane.ai` domain and its `HUGO_BASEURL = https://main.docs.modelplane.ai/`
env var (scoped to `main`) are a one-time setup, done when the first release ships.
The dev project's `main.docs.modelplane.ai` domain and its
`HUGO_BASEURL = https://main.docs.modelplane.ai/` env var (scoped to `main`) are a
one-time setup, done when the first release ships.

To fix a typo or update content in an archived version, push to the release branch.
The versioned deployment rebuilds automatically.

When a new minor ships (e.g. `v0.2.0`), repeat steps 1–4 for `release-0.2`, adding
the `v0.2` entry above `v0.1` in `versions.yaml` on every branch and bumping
`latest` to `0.2` on `main`.
When a new minor ships (e.g. `v0.2.0`):

1. Repeat steps 1–4 for `release-0.2`, adding the `v0.2` entry above `v0.1` in
`versions.yaml` on every branch and bumping `latest` to `0.2` on `main`.
2. Move `docs.modelplane.ai` to the `release-0.2` project so the apex tracks the
new latest.
3. On the old `release-0.1` project, set `HUGO_BASEURL = https://v0-1.docs.modelplane.ai/`
so it stays self-canonical at its permanent subdomain now that it no longer
owns the apex.
3 changes: 2 additions & 1 deletion docs/hugo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ ignoreFiles = ["themes/geekboot/content/.*", "README.md"]
description = "Modelplane documentation."
# "main" on the dev branch; "X.Y" (e.g. "0.1") on release branches.
version = "main"
# Latest stable release. The apex build redirects its root here.
# Latest stable release. Drives the version dropdown and the "not the latest
# release" banners; the apex (docs.modelplane.ai) is this release's own build.
latest = "0.1"
[params.anchors]
min = 2
Expand Down
44 changes: 7 additions & 37 deletions docs/themes/geekboot/layouts/index.html
Original file line number Diff line number Diff line change
@@ -1,40 +1,10 @@
{{ define "main" }}
{{/* The dev (main) docs are built twice: once for the canonical apex
(docs.modelplane.ai) and once for their own subdomain
(main.docs.modelplane.ai). The apex build redirects its root to the
latest release so a reader on the bare domain lands on the latest docs;
the main-subdomain build serves the dev docs so they stay browsable.

Both builds are version == "main"; what tells them apart is the baseURL.
versions.yaml records each version's home URL, so the apex is "the main
build whose baseURL isn't main's own subdomain". Release builds
(version != "main") never redirect and fall straight through.

The redirect mirrors the window.location.replace plus noscript
meta-refresh that list.html uses for section index pages. */}}
{{ $dest := "" }}
{{ if eq .Site.Params.version "main" }}
{{ $here := strings.TrimSuffix "/" .Site.BaseURL }}
{{ $mainURL := "" }}
{{ $latestURL := "" }}
{{ range .Site.Data.versions.versions }}
{{ if eq .version "main" }}{{ $mainURL = strings.TrimSuffix "/" .url }}{{ end }}
{{ if and (eq .version $.Site.Params.latest) .url }}{{ $latestURL = strings.TrimSuffix "/" .url }}{{ end }}
{{ end }}
{{/* Redirect only when main's own subdomain is known and this build isn't it,
and only if a latest release exists to redirect to. Requiring $mainURL to
be set makes the dev-docs build fail open (serve content) rather than
redirect if the main entry is missing from versions.yaml. */}}
{{ if and $latestURL $mainURL (ne $here $mainURL) }}
{{ $dest = printf "%s/" $latestURL }}
{{ end }}
{{ end }}
{{ if $dest }}
<script>window.location.replace("{{ $dest | safeURL }}");</script>
<noscript><meta http-equiv="refresh" content="0; url={{ $dest | safeURL }}"></noscript>
{{ else }}
{{ with .Site.GetPage "/overview" }}
{{ partial "single-list" . }}
{{ end }}
{{/* Every build serves its content directly. The canonical apex
(docs.modelplane.ai) is the latest release's own build, main.docs.modelplane.ai
is the dev build, and each vX-Y.docs.modelplane.ai is an archived release —
the Vercel project and baseURL decide which, so the home page never
redirects. See RELEASING.md § Versioning the docs. */}}
{{ with .Site.GetPage "/overview" }}
{{ partial "single-list" . }}
{{ end }}
{{ end }}
Loading