Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

Repository files navigation

Stoke

A voice-first nutrition tracker built with Expo (React Native + TypeScript) and Supabase — a real, commercial, subscription-based app on its way to the App Store and Google Play.

This repo is a curated portfolio snapshot, not the app's source. It exists to show how the app is built without publishing the full implementation. It contains:

  • code-samples/ — 7 real files from the codebase (the voice-logging pipeline, the adaptive calorie-target algorithm, database schema/RLS, a flagship screen) kept in their original relative paths. They're read-only excerpts, not a runnable project — see that folder's README for details.
  • screenshots/ — a handful of final UI screens.
  • .env.example — documents the environment variables the real app reads, as context for the code samples above; there's no app here to run it against.

There is no build here, no full src/ tree, and no license to reuse any of it — see LICENSE.

What it does

Stoke logs food by conversation instead of search-and-tap. A user describes a whole meal in one breath — items, portions, and roughly when they ate it — and the app parses it into structured, editable log entries with macros. Everything else (dashboard, weight tracking, adaptive calorie targets, trends, profile/onboarding) sits on top of a Postgres schema where every table is protected by Row Level Security.

Voice logging flow

mic press → record (m4a) → groq-proxy Edge Function
  → Whisper transcription (audio → text)
  → LLM structured extraction (text → items, quantities, times as JSON)
  → ranked catalog search + fuzzy match per item
  → confirm sheet (every item editable/removable before it's logged)

The recording never talks to Groq directly. It's uploaded to a Supabase Edge Function (groq-proxy) that holds the Groq API key server-side, verifies the caller's session, enforces a per-user daily usage cap, and pins the model/language — so a model deprecation is a secret update and a redeploy, not an app release. The client only ever sees a transcript back, then a list of resolved food items.

See code-samples/supabase/functions/groq-proxy/index.ts (the transcription/proxy step) and code-samples/src/services/foodResolutionService.ts (the LLM extraction + matching step) for the real implementation.

Tech stack

Area Choice
App framework Expo SDK 54, React Native, React 19, TypeScript
Navigation React Navigation v7 (native-stack + bottom-tabs)
Backend Supabase — Postgres, Auth, Edge Functions, Row Level Security on every table
Voice pipeline Groq (Whisper transcription + LLM structured-output extraction), proxied through a Supabase Edge Function
Food data Self-hosted USDA-derived catalog (ranked Postgres search) with an Open Food Facts fallback for branded/barcode items
State React Context for auth/session; supabase-js owns the session (AsyncStorage + auto refresh)
UI / motion Custom design system, Reanimated, react-native-svg
Search Fuse.js for fuzzy matching against a user's own food history

A technical challenge: adaptive calorie targets

Most trackers nudge your calorie target off a single week of noisy scale data, which overreacts to water-weight swings. Stoke instead fits a least-squares regression line through the last 4 weeks of weigh-ins and only proposes an adjustment when the trend has been consistently off-target across both the 4-week window and the most recent 2 weeks — not just one bad week.

The adjustment itself is deliberately boring: capped at ±100 kcal, at most once every 2 weeks, never below a safety floor, and always presented as a suggestion the user approves rather than something the app applies on its own. The interesting part wasn't the regression — it's the guardrails around it. A trend algorithm that's technically correct but reacts to every noisy data point erodes trust fast; the constraints exist because "mathematically justified" and "a target worth trusting" turned out to be different bars.

See code-samples/src/services/tdeeAlgorithm.ts for the actual regression + guardrail code.

Security model

  • Row Level Security on every table — auth.uid() must match the row's owner; queries also filter by user id explicitly as defense in depth. See code-samples/supabase/migrations/0001_init.sql.
  • No secrets in the client. Only the public Supabase URL and anon key ship in the bundle. The Groq key and the Postgres service role never do — both live server-side as Supabase secrets, used only inside Edge Functions.
  • Sessions are owned by supabase-js, persisted in AsyncStorage with automatic token refresh; the app never handles auth tokens by hand.

Screenshots

Voice logging screen Dashboard screen Food log screen Voice confirm sheet Trends screen

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages