You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CLAUDE.md
+18-7Lines changed: 18 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -80,12 +80,15 @@ telemetry viewer.
80
80
```
81
81
src/
82
82
├── pages/
83
-
│ ├── Index.tsx # ★ Main SPA — file import, tab views, all state orchestration
83
+
│ ├── Index.tsx # ★ Main SPA — file import, tab views, all state orchestration. Also hosts the read-only Leaderboards viewer (plan 0005): consumes a leaderboardHandoff bundle on mount, injects its prebuilt laps/selection, flips a `readOnly` flag that alert-colours the header + hides Coach/Tools/Setups + video/weather/snapshots and labels laps by submitter.
84
+
│ ├── Leaderboards.tsx # ★ Public /leaderboards page (cloud-gated): Track→Course→engine/weight accordion (Group-by-weight + Show-top), opens a group into Index's read-only viewer via leaderboardHandoff; shows uploader avatar thumbnails
85
+
│ ├── DriverProfile.tsx # ★ Public /driver/:username page (plan 0006, anon, case-insensitive via .ilike): avatar + name + opt-in vehicles (no weights/setups) + the driver's approved leaderboard snapshots grouped by course/weight
│ ├── tabs/ # View tabs (GraphView, RaceLine, LapTimes, Coach, Tools; SetupsNotesPanel = Setups+Notes 50/50 split on md+, separate tabs on phones — bodies live in drawer/)
90
93
│ ├── graphview/ # Pro mode: GraphPanel, GraphViewPanel, MiniMap, SingleSeriesChart, GGDiagram, InfoBox, PanelCard (resizable card chrome for relocated Video/Mini-Map panels). The left column collapses via a divider flag tab (any screen size), and Video/Mini-Map can be relocated into the resizable graph stack from the top of the "Add Graph" picker (GraphPanel reports which are active so the host drops its duplicate VideoPlayer — single shared video ref). Split graphs (tablet+): SecondaryGraphStack mirrors the main panel's graph set for a chosen overlay lap in a draggable two-up view, overriding PlaybackContext for its subtree (nested PlaybackProvider) so one cursor lands on the same track position in both laps (distance-mapped via lib/referenceUtils mapIndexByDistance); SecondaryVideo is a literal second, lap-synced <video> for in-session overlay laps.
91
94
│ ├── drawer/ # File-manager drawer tabs (Files, Vehicles/Karts, Device*); SetupsTab + NotesTab also here but mounted as main-view tabs
@@ -115,6 +118,9 @@ src/
115
118
│ ├── sampleData.ts # ★ Bundled sample log seeded as an ordinary file (→ docs/subsystems.md)
│ ├── videoPlaylist.ts # ★ Pure GoPro chunked-video model: parse/order GH/GX/GP/GOPR chunk names, build a virtual timeline (cumulative offsets) + virtual↔local time mapping + planAudioSegments (export audio stitch). useVideoSync swaps the <video> src per chunk; a single file is a 1-chunk playlist
@@ -384,6 +390,7 @@ and the seeder: **→ `docs/i18n.md`**.
384
390
|`VITE_TURNSTILE_SITE_KEY`| Client | Cloudflare Turnstile site key (optional CAPTCHA) |
385
391
|`TURNSTILE_SECRET_KEY`| Server (edge fn) | Turnstile secret — `???`|
386
392
|`VITE_FIRMWARE_MANIFEST_URL`| Client | Override the logger firmware OTA manifest URL. Unset: `main` → production manifest, non-`main`/preview → beta channel (same `isPreviewBuild()` switch). |
393
+
|`SUPABASE_ACCESS_TOKEN`| Build (secret) | Supabase PAT. On a **feature-branch** build (not `main`, not `BETA`), `vite.config.ts` resolves that branch's own Supabase **preview-branch DB** via the Management API (`scripts/resolveSupabaseBranch.ts`) and bakes its creds in, else falls back to the static `*_PREVIEW`/beta creds. Never on `main`/`BETA`/dev/runtime. → plan 0007. |
387
394
|`DOVE_PLUGIN_PACKAGES`| Build | Comma-separated external plugin npm packages. Overrides the default when set. |
388
395
|`ANTHROPIC_API_KEY` / `I18N_SEED_MODEL`| Maintainer tool | Used **only** by `bun run i18n:seed` (`ANTHROPIC_API_KEY` = `???`). Never in the app or CI build. |
389
396
|`VITE_APP_VERSION` / `VITE_GIT_HASH` / `VITE_BUILD_DATE` / `VITE_GIT_BRANCH` / `VITE_GIT_COMMIT_DATE`| Build (auto) | Footer version stamp — **not hand-set**; baked from `package.json` + git in `vite.config.ts`. |
@@ -399,10 +406,14 @@ the dashboard). The beta domain `beta.lapwingdata.com` can't bind to a Branch
399
406
Preview URL, so a separate thin reverse-proxy Worker in `beta-proxy/` owns it and
400
407
forwards to `beta-lapwing.perchwerks.workers.dev` (auto-deployed by the
401
408
`deploy-beta-proxy.yml` workflow on `BETA` pushes that touch `beta-proxy/**`;
402
-
see `beta-proxy/README.md`). Per-branch preview backend: `vite.config.ts``pick()`
403
-
prefers `*_PREVIEW` Supabase creds on any non-`main` branch
404
-
(`WORKERS_CI_BRANCH`/`CF_PAGES_BRANCH`), so beta deployments bake in a preview DB.
405
-
`main` and local dev never read `_PREVIEW`. See README "Deployment".
409
+
see `beta-proxy/README.md`). Backend by branch (`vite.config.ts``pick()`, keyed on
Copy file name to clipboardExpand all lines: README.md
+43-6Lines changed: 43 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -34,6 +34,7 @@
34
34
- Pro graph view with multi-series telemetry charts
35
35
- Reference lap overlay & pace delta comparison
36
36
- Lap snapshots — save a "course fastest lap" per engine, frozen for cross-session comparison (local-first, optionally cloud-synced)
37
+
- Public leaderboards — submit your snapshots and browse fastest community laps by track, course and engine class (with optional weight grouping); opens any group in a read-only viewer (cloud-enabled builds)
37
38
- Video sync with telemetry playback (incl. GoPro chunked recordings — select all chapter files and they play as one continuous video)
38
39
- 9 overlay gauge types (digital, analog, graph, bar, bubble, map, pace, sector, lap time)
39
40
- MP4 video export with overlays & audio (H.264 + AAC)
@@ -166,6 +167,7 @@ view. Older JSON with only `sector_2_*`/`sector_3_*` is read as the two majors.
166
167
|`STRIPE_SECRET_KEY`| No (required for paid tiers) | Stripe secret key used by the `create-checkout-session`, `stripe-webhook`, and `create-portal-session` edge functions (edge function secret — `???`) |
167
168
|`STRIPE_WEBHOOK_SECRET`| No (required for paid tiers) | Signing secret for the `stripe-webhook` endpoint, from the Stripe dashboard webhook config (edge function secret — `???`) |
168
169
|`DELETION_CRON_SECRET`| No (required for scheduled account deletion) | Shared secret the `process-account-deletions` edge function requires in the `x-cron-secret` header. Must match the Vault secret `deletion_cron_secret` that the daily pg_cron job sends (edge function secret — `???`) |
170
+
|`SUPABASE_ACCESS_TOKEN`| No (preview-branch DBs) | Build-time secret: a Supabase **personal access token**. When set, a **feature-branch** build (not `main`, not `BETA`) resolves its own per-branch Supabase preview database via the Management API and bakes those creds in, falling back to the static `*_PREVIEW`/beta creds when the branch has no preview DB. See *Preview-branch backend* below. Never read by `main`/`BETA` builds, local dev, or the runtime app. |
169
171
|`DOVE_PLUGIN_PACKAGES`| No | Build-time: comma-separated external plugin npm packages to load. Overrides the default (`@perchwerks/eye-in-the-sky`, the public AI coach) when set |
170
172
|`ANTHROPIC_API_KEY`| No (translation tooling) | Required by `bun run i18n:seed` to machine-translate locale files (`scripts/seed-translations.mjs`). Maintainer tool only — never read by the app or the standard CI build (`???`). |
171
173
|`I18N_SEED_MODEL`| No | Optional model override for `bun run i18n:seed` (default `claude-sonnet-4-6`). |
on every build; `vite.config.ts` prefers the `_PREVIEW` value of each key
441
-
whenever that branch isn't `main`, and ignores them on `main` and in local dev.
438
+
The build picks its Supabase backend by **git branch**, in three tiers:
439
+
440
+
| Branch | Database | How it's chosen |
441
+
|--------|----------|-----------------|
442
+
|`main`| production | base build vars (`VITE_*` / `HTT_*`) |
443
+
|`BETA`| the shared beta DB | the `*_PREVIEW` build vars |
444
+
| any other branch | that branch's **own** Supabase preview-branch DB | resolved via the Management API, falling back to `*_PREVIEW`/beta when none exists |
445
+
446
+
`BETA` is the shared integration database and is **never** routed onto a per-branch
447
+
DB — only feature branches consult the resolver. Each build logs the result
448
+
(`[backend] Supabase URL baked: … — <tier>`) so a deploy always states which DB it
449
+
baked and why. Set the `*_PREVIEW` vars so non-`main` builds don't touch production:
450
+
451
+
Workers Builds exposes `WORKERS_CI_BRANCH` (Pages: `CF_PAGES_BRANCH`) on every
452
+
build; `vite.config.ts` prefers the `_PREVIEW` value of each key whenever the
453
+
branch isn't `main`, and ignores them on `main` and in local dev.
442
454
443
455
1. Enable **Branching** in Supabase, then copy the preview branch's URL, anon
444
456
key, and project ref from the **Branches** panel.
@@ -455,6 +467,31 @@ whenever that branch isn't `main`, and ignores them on `main` and in local dev.
455
467
is also accepted. Add the Cloudflare preview URL to the preview branch's
456
468
**Auth → Redirect URLs** so cloud sign-in works there.
0 commit comments