SV-1 — System Interfaces

Viewpoint: the system's components and the interfaces between them.

flowchart TB
  subgraph browser [Browser]
    pages[Prerendered pages]
    hydration[Client hydration - src/lib/*-api.ts]
    leaflet[Leaflet map]
  end

  subgraph worker [Worker - src/worker]
    router[Router - index.ts]
    handlers[Handlers - handlers/*.ts]
    queries[Query builders - queries.ts, surfer-queries.ts]
    docs[API docs - openapi.json, /api/docs]
    sched[scheduled - Instagram scoring + cache refresh]
  end

  assets[Static assets - dist/ via ASSETS binding]
  d1[(D1 SPOTS_DB)]
  r2[(R2 public bucket)]
  graphapi[Instagram Graph API]

  pages --> hydration
  hydration -->|GET /api/*| router
  leaflet -->|GET /api/spots/map?bbox| router
  router -->|non-API paths| assets
  router --> handlers
  handlers --> queries --> d1
  router --> docs
  pages -->|media URLs| r2
  sched --> graphapi
  sched --> d1

Interface contracts:

Interface Contract
Browser ↔ Worker API OpenAPI 3.1 spec at docs/api/openapi.yaml; JSON envelopes; errors {error, code}; GET only
Worker ↔ D1 Prepared statements via the SPOTS_DB binding; FTS5 for search
Worker ↔ static assets ASSETS.fetch fallthrough; /spots/:slug + /surfers/:slug rewritten to __detail shells
Site ↔ R2 Public bucket URLs baked into payloads (hero images, clips)
Cron ↔ Instagram Graph API Best-effort; results cached in D1 (instagram_feed_cache, instagram_account_scores)

Layer rules (machine-checked by npm run health via dependency-cruiser): no circular dependencies; src/lib never imports src/worker; src/** never imports scripts/**.