Skip to content

feat: environment-aware datasette base URL - #604

Closed
stefanb wants to merge 5 commits into
docs/claude-mdfrom
feat/env-aware-datasette-url
Closed

feat: environment-aware datasette base URL#604
stefanb wants to merge 5 commits into
docs/claude-mdfrom
feat/env-aware-datasette-url

Conversation

@stefanb

@stefanb stefanb commented Aug 16, 2026

Copy link
Copy Markdown
Member

Stacked on #603 (docs/claude-md) — merge that first; this PR shows only the datasette-wiring work.

Problem

Every website environment queried the stage datasette: https://stage-data.podnebnik.org was baked into the JS bundle (hardcoded in two of the three islands). Production served stage data, local instances couldn't use a local datasette, and previews were implicitly tied to stage.

What this does

Shared resolvercode/datasette-base.ts, consumed by all three islands (ERA5 api.ts, legacy ali-je-vroce/constants.ts, temperatura/heatmaps.jsx). Precedence:

  1. VITE_DATASETTE_URL build-time override (compose → 127.0.0.1:8001; manual dev → :8010; preview builds → per-PR)
  2. Fixture mode → the recorded stage base (2,087 URL-keyed fixtures stay valid)
  3. podnebnik.org / stage.podnebnik.orgsame-origin /data — the gateway already routes each host's /data prefix to its own datasette, so the single promoted image reaches prod data on prod and stage data on stage, with no CORS
  4. Fallback → stage base (Node/tests, localhost, previews without their own datasette)

Local — docker compose wires the website dev server to the local datasette container.

Previews (preview-deploy label) — docker-preview.yaml detects whether the PR touches the datasette path set (same list as docker-data.yaml; PR-files API, fail-closed):

  • touches data → builds ghcr.io/podnebnik/data:pr-<N> (db-export generation + multi-arch runtime in one job), bakes /data into the website bundle, and applies the preview-data label after the image push
  • doesn't → bakes the stage base and retracts a stale preview-data label

The Helm chart gains a previewDatasette component (Deployment/Service + /data HTTPRoute rewrite mirroring the live stage/prod route shape; templated rollout revision so each push re-pulls the mutable pr-<N> tag). Chart 1.1.0 → 1.2.0; default render unchanged.

⚠️ Infrastructure prerequisite (sledilnik/infrastructure)

The per-PR-preview half needs the podnebnik-website-preview ApplicationSet to enable the component when the PR carries the preview-data label, e.g. in the generator/template:

previewDatasette:
  enabled: true          # gate on the preview-data PR label
  image:
    tag: "pr-{{ .number }}"
  revision: "{{ .head_sha }}"   # forces re-pull of the mutable tag on each push

Everything else (prod/stage/local) works without any infra change. Ops note: prod pages will start reading data.podnebnik.org, whose image tag is pinned by hand in the infra repo — promote the data image alongside the website when relevant.

Verification

  • yarn typecheck:gate — OK (zero-error allowlist holds)
  • yarn test — 100/100, fixture base guard passes (resolver + new VITE_DATASETTE_URL="" pin land atomically — "" under the old ?? logic would have broken the suite)
  • yarn snapshot:check — byte-identical, 0 fixture misses (the resolver keeps import.meta.env.* as literal member expressions so the snapshot define block still applies)
  • helm template — preview render shows datasette Deployment (pr-999, revision templated) + /data route; default render identical to before
  • Local e2e: compose website dev server injects VITE_DATASETTE_URL=http://127.0.0.1:8001; local datasette verified serving climate-si

🤖 Generated with Claude Code

@stefanb
stefanb marked this pull request as draft August 16, 2026 17:13
github-actions Bot and others added 5 commits August 17, 2026 02:44
updates image podnebnik/website tag 'main-80b268f-1786858826' to 'main-bbd4950-1786939086'
Every environment previously queried the stage datasette — the base URL
was baked into the JS bundle, hardcoded in two of the three islands.

A shared resolver (code/datasette-base.ts) now picks the base per
environment: VITE_DATASETTE_URL override > fixture base > same-origin
/data on deployed hosts (podnebnik.org -> its own datasette,
stage.podnebnik.org -> stage-data, via the already-live gateway routes)
> stage default for Node/tests/localhost. One promoted image therefore
reaches the right data on both stage and prod, with no CORS.

Local: docker compose wires the website dev server to the local
datasette (127.0.0.1:8001); bare `yarn start` keeps the stage default,
opt in with VITE_DATASETTE_URL=http://127.0.0.1:8010 for invoke
datasette.

Previews: docker-preview.yaml now detects whether the PR touches the
datasette path set (same list as docker-data.yaml, fail-closed via the
PR files API). If so it builds ghcr.io/podnebnik/data:pr-<N> (db-export
generation + multi-arch runtime in one job), bakes /data into the
website preview bundle, and applies the preview-data label AFTER the
push; otherwise it bakes the stage base and retracts a stale label. The
chart gains a previewDatasette component (Deployment/Service + /data
HTTPRoute rewrite, templated rollout revision for the mutable pr-N tag)
that the infra ApplicationSet enables on the preview-data label.

Fixture safety: the resolver reads import.meta.env.* as full literal
member expressions (the snapshot define block replaces those exact
tokens), fixture mode pins the recorded stage base, and vitest now pins
VITE_DATASETTE_URL="" so a shell-exported override can no longer fail
the suite. Verified: typecheck-gate OK, 100/100 unit tests, snapshot
byte-identical with 0 fixture misses, helm template renders the preview
component and an unchanged default, local compose end-to-end.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@stefanb

stefanb commented Aug 18, 2026

Copy link
Copy Markdown
Member Author

Superseded by #609 — same change rebased directly onto main (unstacked from #603, CLAUDE.md changes dropped).

@stefanb stefanb closed this Aug 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants