A cat sitting in front of an Apple computer

NASA APOD on the home page without blocking first paint


I wanted NASA’s Astronomy Picture of the Day behind the home page. I did not want the home route waiting on a government API before HTML shipped.

The slow version called NASA during SSR. Navigation from the blog back to home felt sticky. The fix was boring: static shell first, picture second.

Build-time fetch, static files at the edge

scripts/fetch-apod.mjs runs before npm run build and npm run dev (prebuild / predev in package.json). It:

  1. Calls the NASA APOD API (with NASA_API_KEY in .env, or DEMO_KEY as fallback)
  2. Prefers hdurl when present, then resizes to a 1920px-wide WebP (~120 KB)
  3. Writes public/apod/today.json and public/apod/background.webp

The home page HTML is pre-rendered. A small client script runs after paint:

if (window.matchMedia('(prefers-reduced-data: reduce)').matches) return;

const res = await fetch('/apod/today.json');
if (!res.ok) return;
const apod = await res.json();
document.body.style.setProperty('--apod-image', `url("${apod.imageUrl}")`);

today.json points at /apod/background.webp, not a hotlinked NASA URL. If the fetch fails, the page is still readable—no spinner, no blank screen.

CDN cache on static APOD assets

Cache headers in public/_headers keep repeat visits cheap:

Cache-Control: public, max-age=3600, s-maxage=86400, stale-while-revalidate=86400

/apod/* is served as static assets from dist/client/ (via the ASSETS binding)—no Worker invocation, no runtime NASA call on page load.

A daily GitHub Action can commit fresh APOD files when you want the background to update without rebuilding on every NASA publish.

Respect reduced data

Skip the background fetch when the visitor prefers less bandwidth (prefers-reduced-data: reduce). Optional delight should not tax every visitor.

This pattern is part of Rebuilding mayfield.io. For why /apod/today.json does not show up in Worker logs, see Why Cloudflare Worker logs only show some routes.


Hero photo: Apple computer cat, freely licensed on Wikimedia Commons.