**Note** from Bead: Firewatch Camera Grid · [canonical source](https://redfish.acequia.io/guerin/.agents/65783732-7907-4a36-983a-3b015e75e80b/2026-06-13/notes/00-design-questions-and-vision.md) · session 2026-06-13 · discussion: Talk: Firewatch Camera Grid
## What I found (grounding) - **santafe.live IS the catalog manager** ("Image Cache Manager"): Leaflet + canvas timeline + thumbnail **grid** + **map**, side by side. Per-image it already keeps two **sidecars**, keyed by a hash `id`: - `imageMeta/<id>.json` → `{url, id, displayName, contentType, lastUpdate, calendarDate, timeUTC, notes}` — identity + **time**. - `imagePose/<id>.json` → `{Latitude, Longitude, Elevation, heading, pitch, roll, fov, fovy, far}` — **space + orientation**. This is **already an oriented-imagery pose schema** (currently mostly null for historical photos, set by dragging on the map). - **AlertWildfire source** (`alertcalifornia-cams`): per-camera `telemetry-<id>-<unix>.json` with a `frames[]` array — each frame has `filename, ts, camAzimuth, camElevation, camZoom, camViewWidth (≈hFOV), camName, camHasPTZ/camHasAz` — plus `getCameraDataByLoc.json` giving each camera's `lat/lon`. Cameras are **fixed-position, variable-orientation** (PTZ per frame).
## Recommendation on the PTZ sidecar (you asked: "is that what you'd recommend?") **Yes — sidecar, and specifically reuse santafe's `imagePose` schema.** Reasoning: 1. **The schema already fits.** `camAzimuth→heading`, `camElevation→pitch`, `camViewWidth→fov` (and `fovy` from aspect), camera `lat/lon→Latitude/Longitude`, `roll≈0`. The telemetry maps 1:1 onto the existing `imagePose` fields — no new schema, the forked manager's editor works unchanged. 2. **Image-addressable pose is the right primitive.** A per-image sidecar (keyed by image id, in a parallel `imagePose/` tree) keeps the pose a discrete resource that composes regardless of consumer — the manager edits it, the 3D viewer reads it, and a future STAC oriented-imagery Item references it as an asset. This is exactly your instinct for "when oriented imagery lands in STAC, go sidecar." Sidecar ≠ inline-in-STAC-properties: the sidecar is the **source of truth**; the STAC Item *binds* it (asset href) or *mirrors* it (projection), the way the incident-viewer's `incidents.json` is a projection of the STAC, not the master. 3. **Telemetry bundle → per-frame sidecar is a one-time derivation** (a small skill, like `catalog-incident`): walk `frames[]`, join camera `lat/lon`, write `imagePose/<id>.json` + `imageMeta/<id>.json` per frame. Re-runnable; idempotent; leaves the vendor telemetry untouched. 4. **Human-in-the-loop stays meaningful.** Where telemetry is absent/wrong (older AlertWildfire cams without az, or a mis-pointed frame), the manager's map/3D editor lets you set the pose by hand — same sidecar, same fields. Telemetry auto-fills; the human corrects. **One caveat to decide:** AlertWildfire frames are *fixed viewpoint + look-direction*, not an independently placed map footprint like santafe's historical photos. The 2D-map representation of such a frame is a **view cone / azimuth wedge from the camera point** (what the incident-viewer already draws), not a draggable marker. The 3D view is where the pose really reads. So the fork's "set 2D space" becomes "set/confirm the camera point + look azimuth," with the per-frame az/fov driving a wedge.
## Where this is ultimately going (managing catalogs) The through-line across santafe.live, the incident-viewer, geo.camera, and AlertWildfire is **one problem**: *place imagery in (time, position, orientation) and make it a queryable, viewable catalog.* The convergence I see: - **One catalog substrate, two faces.** *Managing* (set/confirm pose + time) and *viewing* (consume pose + time) are the same catalog seen from two sides — this is the incident-viewer plan's "Epic-4 catalog-manager dual surface." The firewatch fork is the manager face; the incident-viewer is the viewer face; they should converge on the **same sidecar pose schema** so an edit in one shows up in the other. - **Pose sidecar = the universal primitive.** Manual placement (santafe drag), PTZ telemetry (AlertWildfire), MISB KLV per-frame (incident-viewer FMV), and live cameras (geo.camera) all produce *the same thing*: a viewpoint + look direction (+ fov). Storing it as an image-addressable sidecar makes it standard-agnostic and ready to become a STAC oriented-imagery asset when that lands — without re-versioning the catalog. - **Grid → map → 3D is a zoom of fidelity, not separate apps.** Grid = "what frames exist when" (contact sheet on a timeline); 2D map = "where the cameras are + which way they look" (wedges); 3D map = "stand at the camera and see the posed image on terrain" (the incident-viewer billboard/projection). Same items, three lenses, one timeline. - **Cameras as agents (the ecology endgame).** A live firewatch camera is a bead/agent that streams new posed frames into the catalog; the manager is where a human curates/corrects pose; the viewer is where anyone consumes it. The catalog is the shared commons; the timeline is the clock. The firewatch fork is a concrete step toward that — starting from an archived incident (Sandy) so the static case is solid before live feeds.
## Open questions (please answer before I plan/build) 1. **Deploy target.** "Deploy the artifact in your bead" — do you want it served at the **bead's own URI** (`…/65783732…/repo/dist/` or an `app/` subpath under the bead), or deployed to a **site path** (e.g. `redfish.acequia.io/guerin/apps/firewatch-camera-grid/` like the incident-viewer)? Git repo in the bead at `repo/` either way (per the git-in-bead policy) — this is just about where the built artifact is served. 2. **3D map engine.** For the "3D map view," reuse **TaosEngine** (consistent with the incident-viewer — posed billboards/wedges, terrain, the camera glyphs I just shipped), or a lighter 3D (MapLibre/CesiumJS globe) since this is a manager not the full viewer? My lean: TaosEngine, to converge with the viewer and reuse the camera-marker + billboard work. 3. **Canonical pose store: sidecar now, STAC later — or STAC now?** I recommend **sidecars as source-of-truth now** (reuse santafe's `imagePose`/`imageMeta`), with a STAC projection generated from them when needed (mirrors the incident-viewer's STAC↔projection split). Confirm, or do you want STAC Items as the primary store from day one? 4. **Scope of cameras.** Start with **just the Sandy archive** (`2026-CA-SandyFire/ops-alertcalifornia/`, e.g. 15801 + whatever other cams have frames), or the whole AlertCalifornia camera set in `getCameraDataByLoc.json` (hundreds, mostly without local frames)? My lean: Sandy archive first (real frames + telemetry), camera-location file only to place markers. 5. **Fork mechanics.** Copy santafe.live's `index.html/index.js/timeline.js/styles.css` into `repo/` and adapt in place, or treat it as a from-scratch rewrite that borrows the layout? My lean: copy + adapt (faster, keeps the working timeline/grid/map), then swap the data layer to the telemetry-derived sidecars. 6. **Sidecar location for derived frames.** Write derived `imagePose/imageMeta` into the **bead** (offered, like all bead outputs), or are we eventually binding them next to the frames under `simtable.acequia.io/incidents/.../ops-alertcalifornia/`? (Per the cataloging-incident rule I won't write into `incidents/**` without your say-so — so default is bead-local, offered.)