Skip to content

migrate public pages to server loads + direct prisma

jedmund requested to merge jedmund/server-loads into main

Created by: jedmund

Follow-up to #72. Addresses audit items #6, #7, and #13: public page loads stop self-HTTP-hopping through /api/* and read from Prisma directly via a shared query layer.

What changed

  • New $lib/server/queries/ — one file per entity (albums, photos, garden, projects) holding findMany/findUnique wrappers plus the shared include/select/orderBy constants. API routes and server loads both consume this layer, so the Prisma shape lives in one place.
  • 6 public pages migrated to +page.server.ts: /, /albums, /photos, /garden, /labs, /work/[slug]. Each page now reads directly from Prisma instead of fetching its own API.
  • Homepage parallelizedPromise.all([lastfm, projects]) instead of sequential awaits.
  • Cache headerscache-control: public, max-age=1800, stale-while-revalidate=86400 on public pages (homepage uses max-age=300 since now-playing is hotter).
  • API routes kept intact for writes, admin, and external consumers (RSS, client-side infinite scroll on albums/photos). They now route through the same query layer too — no duplicated Prisma shapes.

Trade-offs worth noting

  • Query logic is duplicated across page loads and API routes at the caller level. Factored into the query layer so the where/include/orderBy shapes live in one spot; callers just pick the function.
  • Redis caching on API routes is bypassed for page loads (direct Prisma). For this traffic shape it's a non-issue; cache headers let the browser/CDN handle it at the edge.
  • Prerendering still requires DATABASE_URL at build time if you ever want to opt in per-page — not doing that here.

Commit sequence

One commit per concern for review:

  1. extract prisma queries into shared query layer — refactor only, no behavior change
  2. migrate /albums to server load
  3. migrate /photos to server load
  4. migrate /garden to server load
  5. migrate /labs to server load
  6. migrate /work/[slug] to server load
  7. migrate homepage to server load, parallelize data fetching
  8. fix formatting

Test plan

  • Home, /albums, /photos, /garden, /labs, /work/[slug] render with SSR'd data (no loading flash, no client fetch visible in Network tab on first load)
  • Homepage Network tab shows LastFM and projects loading in parallel, not serially
  • /albums and /photos infinite-scroll still fetches more pages from /api/albums and /api/photos
  • Admin album/project/garden list pages still work (they still go through /api/*)
  • /work/[slug]?preview=<token> previews a draft project correctly
  • A password-protected project shows locked state to non-unlocked viewers
  • RSS/external consumers of /api/* still get identical payloads
  • curl -I on any migrated page shows the expected cache-control header

Merge request reports

Loading