Skip to content

Docs site custom domain (docs.nonlocally.org)

This site is a Material for MkDocs build published by .github/workflows/docs.yml: every push to main that touches docs/**, mkdocs.yml or requirements-docs.txt runs mkdocs build --strict and mkdocs gh-deploy, which pushes the built site to the gh-pages branch that GitHub Pages serves. The site lives at https://docs.nonlocally.org/; the GitHub-provided URL https://englund-garage.github.io/openweb-marimo-platform/ redirects there, path included.

How the domain is wired

Three pieces, in three places:

Piece Where Who changes it
docs/CNAME containing docs.nonlocally.org this repo. MkDocs copies it to the site root, gh-deploy pushes it to gh-pages, and GitHub Pages reads the custom domain from it on every deploy anyone, through a PR
DNS: docs.nonlocally.org CNAME englund-garage.github.io the nonlocally.org zone on Cloudflare, DNS only (grey cloud), TTL auto whoever holds that Cloudflare zone
TLS certificate and Enforce HTTPS GitHub Pages provisions a Let's Encrypt certificate once the DNS check passes; the checkbox is under repository Settings → Pages a repository admin

Why DNS-only. GitHub issues and renews the certificate with an HTTP-01 challenge against the hostname. Through Cloudflare's proxy that challenge is unreliable and Enforce HTTPS can stay greyed out. mit.nonlocally.org is already DNS-only in the same zone.

Why a CNAME file rather than the settings page. The site publishes from a branch (Pages build_type: legacy, source gh-pages, path /), and GitHub takes the custom domain from the CNAME file at the root of that branch. Setting the domain in the UI commits the same file to gh-pages, which the next gh-deploy --force --no-history would drop again. Keeping it in docs/ makes the domain part of every deploy.

What moves with the origin

site_url in mkdocs.yml is the ONE browser origin the marimo-proxy feedback relay trusts (DOCS_SITE_URL in k8s/marimo_proxy.py, route-scoped CORS on /api/marimo/feedback); tests/unit/test_docs_feedback.py pins the two together, so a domain change is one PR that touches both. The same PR carries every link to the feedback form and the docs: docs/javascripts/feedback.js, the workspace wrapper (k8s/workspace/index.html and the ConfigMap copy in k8s/marimo-editor-deployment.yaml), marimo_tools.py (DOCS_FEEDBACK_URL), the Open WebUI banner (k8s/openwebui-ui-config.json) and the models landing page (k8s/models-landing/index.html; regenerate the yaml with python3 scripts/build_models_landing.py).

After the merge:

  • docs workflow: builds and pushes gh-pages with the CNAME file. Automatic.
  • build-images then deploy-staging → production: rebuilds the marimo-proxy image (the relay's new default origin) and rolls it out. Automatic; the pipeline recreates the marimo editor once (about 3–4 minutes of 502, measured in #584).
  • Banner: python3 scripts/sync_ui_config.py --apply (admin key; the script plans by default).
  • Tool file: redeploy marimo_tools.py (the deploy-tool skill / kubectl cp).
  • Models landing: kubectl apply -f k8s/models-landing/models-landing.yaml.

The last three are cosmetic until they happen: the old GitHub URL redirects to the new domain, so stale links keep working.

Cutover order

  1. DNS record first. Until docs.nonlocally.org resolves, a deployed CNAME makes GitHub redirect the old URL to a name that does not exist. The site would be down for exactly that window.
  2. Merge the PR that adds docs/CNAME and moves site_url. The docs workflow runs on the merge and the Pages custom domain follows.
  3. Certificate, then Enforce HTTPS. GitHub requests the certificate once its DNS check passes (minutes, up to an hour). A repository admin then ticks Enforce HTTPS (Settings → Pages), or:

    gh api -X PUT repos/Englund-Garage/openweb-marimo-platform/pages -F https_enforced=true
    
  4. Verify the domain for the org (recommended). Organization settings → Pages → Add a domainnonlocally.org, then the TXT record GitHub shows at _github-pages-challenge-englund-garage.nonlocally.org. A verified domain, and its immediate subdomains, cannot be claimed by another GitHub account if the CNAME is ever left dangling.

Verify

dig +short docs.nonlocally.org CNAME                       # englund-garage.github.io.
curl -sI https://docs.nonlocally.org/ | head -1            # HTTP/2 200
curl -sI https://englund-garage.github.io/openweb-marimo-platform/feedback/ | grep -i '^location'
#   location: https://docs.nonlocally.org/feedback/
curl -sI http://docs.nonlocally.org/ | grep -i '^location' # https://… once Enforce HTTPS is on
gh api repos/Englund-Garage/openweb-marimo-platform/pages \
  --jq '{cname, https_enforced, protected_domain_state}'
# The relay trusts the new origin (after the proxy rollout): 204 with the allow-origin header.
curl -s -o /dev/null -D - -X OPTIONS https://mit.nonlocally.org/api/marimo/feedback \
  -H 'Origin: https://docs.nonlocally.org' -H 'Access-Control-Request-Method: POST' \
  -H 'Access-Control-Request-Headers: content-type' | grep -i 'HTTP/\|allow-origin'
FEEDBACK_E2E=1 OPENWEBUI_API_KEY= pytest tests/goal/test_feedback_docs_relay.py -q

Rollback

Delete docs/CNAME and set site_url back to https://englund-garage.github.io/openweb-marimo-platform/ (the relay default and the links follow; the pinned tests say which). Merge: GitHub drops the custom domain on the next deploy and the github.io URL serves again. Remove the DNS record too unless the domain is verified for the org — a dangling CNAME is the takeover case step 4 guards against.