Hold That Thought — Project Handbook (Flutter · Supabase · OpenAI)
Hold That Thought — Project Handbook (Flutter · Supabase · OpenAI)
App ID: com.holdthatthought
One-liner: Record thoughts (AAC .m4a), store locally + Supabase (DB + Storage), auto-transcribe (OpenAI Whisper), auto-summarize (Edge Function). Dark M3 “glass” UI. Offline-first with durable retries.
1) Architecture
- Flutter/Android: audio record/play; dark M3; glass cards.
- Storage:
- Local app dir for audio.
- Supabase Storage bucket
thoughts-audioat path<uid>/<clientId>.m4a. - Supabase Postgres table
thoughts.
- Auth: Supabase anonymous auth; sessions persist + auto-refresh; all network paths re-ensure anon session.
- Transcription: HTTP Whisper (
Authorization: Bearer <OPENAI_API_KEY>); offline queue + retries. - Summaries: Edge Function
indexvalidates JWT; uses service-role client; adopts orphan rows; upsert by(user_id, client_id); returns summary. Local OpenAI fallback only if Edge unavailable. - Offline: durable queues (upload + transcription); auto-summary on upload complete; reconnect sweep to backfill.
2) Key Files
Bootstrap/Config
lib/bootstrap.dart— dotenv;Supabase.initialize(persistSession/autoRefresh); starts Sync + reconnect sweep + upload→summary listener.lib/core/openai_key.dart— resolver + masking.lib/core/auth_utils.dart—ensureSession()+ensureSignedInUid().lib/services/edge_client.dart— Supabase Functions invoke.
Capture/Transcription/Summary/Sync
lib/pages/capture_page.dart— capture UI + enqueue upload.lib/services/transcription_service.dart— Whisper.lib/services/transcription_retry_queue.dart— backoff + pause/resume.lib/services/upload_service.dart— queue, event stream, Storage upload.lib/services/sync_service.dart— upload→summary hook + reconnect sweep + auth hardening.lib/services/summary_service.dart— Edge-first; strict prompt (return only a 1–2 sentence summary; no chatter).lib/widgets/thought_detail_bottom_sheet.dart— single Summary button + spinner; persistent summary card; transcript edit pencil in header.lib/repositories/thought_repository.dart— smart status updates.
Settings/Diagnostics
lib/pages/settings_page.dart— glass cards; Fix Connection; key paste/validate (restart-safe).
Theme & Build
lib/theme/app_theme.dart— dark M3.tool/pad_icon.dart,flutter_launcher_icons,flutter_native_splash— launcher/splash.tooling/build_release.ps1— one-click release pipeline.
Edge/Policies
supabase/functions/index.ts— CORS; JWT; service client; adopt orphan; upsert (user_id, client_id); returns{id, clientId, summary}.supabase/policies/rls_thoughts.sql— RLS forthoughts.- Storage bucket
thoughts-audiowith per-user RLS: first path segment ==auth.uid().
3) Shipped Highlights
- Secrets via
.env+ secure storage; masked logs. - Anon auth with persisted session; all sync paths re-ensure session.
- Recording to
.m4a; upload tothoughts-audio/<uid>/<clientId>.m4awith retry. - Retry queues (401 → pause; resume on key fix); robust offline→online flows.
- SummaryService Edge-first with clean upsert and strict “summary-only” prompt.
- UI polish: single Summary button; spinner; persistent summary card; chips only when true (
✨ Summarizedwhensummary.trim().isNotEmpty). - Diagnostics & key validate; context-safe async; modernized APIs (SharePlus, PopScope, withValues(alpha)).
- Release builds green; Impeller/Vulkan OK.
4) Current Status (Today)
✅ E2E on device: record → upload → auto-transcribe → auto-summary.
✅ Reconnect sweep backfills; badges flow: Local → Uploaded → Transcribed → ✨ Summarized.
✅ Storage + RLS live; DB aligned: summary, transcript, client_id (NOT NULL, unique per user), updated_at trigger.
5) Next Up
Polish & Perf
- Waveform seek bar; micro-animations for chips.
- (Optional) Storage perf index:
storage.objects (bucket_id, first_segment).
Edge telemetry
- Structured logs/metrics for
index.ts(latency, token usage, failures).
QA
- Long offline sessions; large files; concurrent uploads.
6) Commands
Build & install
flutter clean
flutter pub get
dart run tool/pad_icon.dart 0.97
dart run flutter_launcher_icons
dart run flutter_native_splash:create
flutter build apk --release
adb devices -l
adb -s <ID> install -r build/app/outputs/flutter-apk/app-release.apk
Logs
adb logcat -c
adb logcat *:S flutter:V AndroidRuntime:E ActivityManager:E > app_startup.txt