Skip to content

ADR-016 — All external assets resolved at build time

Status · Accepted Date · 2026-04-28 TA anchor · §stack · §constraints

Context

The application currently depends on several external URLs at runtime: NASA Images API for mission imagery, Three.js GitHub CDN for planet textures, Wikimedia Commons for agency logos, and Google Fonts for typography. These dependencies are brittle (URLs change, services go down, rate limits apply) and prevent true offline use. At production scale with millions of users, external runtime dependencies are a reliability and performance risk.

Decision

All external assets are resolved at build time by GitHub Actions scripts. Nothing in the production bundle fetches from a third-party URL at runtime. Assets are served from the application's own host.

The asset types and their build-time resolution:

  • Google Fonts — downloaded via scripts/fetch-assets.ts, committed to static/fonts/ (implemented in Slice 1)
  • Planet textures — downloaded from Solar System Scope (CC BY 4.0; the originally-named Three.js r128 source did not actually carry the 2k_*.jpg set), written to static/textures/ (implemented in Slice 3 / 3a-2)
  • Agency logos — downloaded from Wikimedia Commons during build, written to static/logos/ (scheduled for Slice 4 with the mission library)
  • Mission imagery — fetched at build into static/images/missions/[id]/. Source priority (agency-first, NASA as fallback library) is locked in ADR-046; ADR-016 only requires build-time bundling, not NASA-only sourcing.

This ADR locks the approach (build-time, no runtime third-party fetches) for all four categories. The two unimplemented categories will be added to scripts/fetch-assets.ts in Slice 4 alongside the mission library and mission arc; the script's structure (per-category async function, fail-fast on individual asset, written to static/) is the contract for those additions.

Rationale

Build-time resolution eliminates all runtime third-party dependencies. The app works fully offline after first load. Images are served from the application's own CDN — faster for users than fetching from NASA or Wikimedia. Rate limits apply at build time (rare, recoverable) not at user time (frequent, user-facing). The build scripts are owned code — no third-party proxy service required.

Alternatives considered

  • Runtime proxy (owned) — a GitHub Actions job could serve as a proxy at runtime via a worker. Adds operational complexity; build-time is simpler and more robust.
  • Third-party image CDN — Cloudinary, Imgix etc.; introduces third-party dependency; rejected.
  • Keep external URLs — simplest; brittle; fails offline; rejected.

Consequences

Positive: fully offline-capable; no runtime third-party dependencies; faster image loading; no rate limit risk for users. Negative: build takes longer (asset fetch adds ~2min); weekly rebuild needed for fresh mission imagery; storage in repo increases (logos, textures ~5MB; mission images depend on count/size — managed via Git LFS if needed).

Implementation notes

scripts/fetch-assets.ts — runs in CI before npm run build (executed via npx tsx). NASA Images API key in GitHub Actions secret. Graceful fallback: if NASA API fails for a mission, placeholder image used. Git LFS for images if size becomes a concern.

Orrery — architecture documentation · MIT · No tracking