Inspiration
Every wearable — Garmin, Apple Watch, Strava — is excellent at collecting numbers: heart rate, pace, sleep, training load. But having the data isn't the same as understanding it. We noticed a pattern in our own (and friends') behavior: after a hard workout, we'd screenshot our watch data, paste it into ChatGPT, and manually re-explain our fitness level, goals, and recent history just to get a useful answer. Every single time. The AI model was smart enough — the problem was that we had to be the context engine, rebuilding our own history from scratch in every conversation. We wanted to build the layer that remembers, so the question-to-insight loop has zero friction — without handing a third party our raw health history to do it.
What it does
Numa ingests workouts (CSV export, GPX file, or manual entry), builds a rolling personal baseline for each metric per activity type, tracks long-term progress trends, and runs statistical correlation tests against hypotheses like "does my sleep affect next-day pace?" or "does training load raise my resting heart rate?" Only correlations that pass a significance and sample-size threshold ever surface to the user. An LLM narration layer then explains these pre-verified facts in plain language — grounded, cited, and explicitly hedged, referencing possible contributors rather than a single diagnostic claim. You can ask Numa "why was my run slower today?" or "am I actually improving?" and get an answer backed by your own real history, not a generic response — and not your raw data either (see the privacy note below).
How we built it
We designed the system as five progressive layers, deliberately kept separate so each is independently testable and explainable:
- Raw workouts — normalized from CSV/GPX/manual entry into a canonical metric schema
- Baselines — a BullMQ worker computes rolling mean/stddev per (user, activity, metric, window) across two windows: 14-day (what's normal now) and 90-day (long-term trend)
- Per-workout comparison — derived live at read time (never stored) using z-scores against the short-window baseline
- Progress trend — simple month-over-month comparison per metric, deliberately kept as a plain comparison rather than a regression, since it's easier to explain and defend
- Correlation engine + LLM narration — three pre-defined hypothesis tests (sleep→performance, effort-rating→heart-rate, training-load→heart-rate) run per user via Pearson correlation. A pattern is only written if it clears r ≥ 0.4 with at least 8 paired samples. A fixed template per check generates the human-readable summary — the LLM never invents the statistic, it only narrates a summary that was already written by code.
The narration layer (Groq) never receives raw health data. It only receives: a pseudonymous display name (email prefix only), aggregated statistics (baseline means/stddevs, correlation r-values, % changes — all pre-computed by pure functions), the user's own last 4 reflection notes (date-stamped, no workout IDs or identity links), and effort/energy ratings. Output is constrained to structured JSON, and the system prompt explicitly forbids citing any number not present in the context block, so the model can't fabricate a statistic even if asked to.
The stack: Next.js 16 frontend, Express 5 + BullMQ backend, Supabase (Postgres + Storage) for persistence, and Groq for the narration layer. We also built a synthetic data generator that models realistic day-to-day physiological state (sleep, training load, fitness trajectory) and derives workout metrics from it, so the correlations our engine discovers are real relationships we intentionally modeled — not hallucinated by an LLM.
Challenges we ran into
The hardest problem wasn't the AI — it was resisting the urge to let the AI do too much. Our first instinct was to hand the LLM a user's full history and let it "figure out" patterns, but that meant we couldn't verify or defend any claim it made — a serious problem for a health product. We rebuilt the architecture so the LLM is strictly a narrator: every number and every correlation it can reference was already computed and verified by a pure statistical function before the model ever sees it, and its access to raw data is minimized by design, not by policy. This made the system slower to build but far more defensible, and it directly shaped how we think about "Responsible AI" — not as prompt engineering, but as an architectural constraint on what the model is even allowed to see and say.
Real-world data availability was our other early concern. Wearable APIs (Apple Health, Garmin, Fitbit) each have separate, slow-to-approve integration paths that would have consumed most of our timeline for zero product benefit. We solved this by building a physiologically-grounded synthetic data generator instead — which had the side benefit of giving us full control over ground truth, so we could verify our correlation engine was finding real signal, not noise.
Accomplishments that we're proud of
We're proud that Numa's core AI safety property is architectural, not just promised: the model literally cannot cite a statistic it wasn't given, because the prompt only ever contains pre-verified, aggregated facts — never raw readings, never a persistent identifier. Row-level security isolates every user's data at the database layer, the entire stats pipeline runs 100% offline if no LLM key is configured, and deleting an account cascades through every table — workouts, reflections, patterns, and chat history all gone. We're also proud of the layered stats pipeline itself — baselines, comparisons, trends, and correlations all work independently of the LLM, so a judge can see the system producing real, explainable insight even with the AI layer switched off entirely.
A note on privacy: Numa sends the LLM the minimum needed to answer a question well — pseudonymized display data, pre-computed statistics, and the user's own reflection notes — never raw workout data, never a persistent user ID. The architecture is designed with HIPAA/GDPR principles in mind (data minimization, pseudonymization, user-controlled deletion, no raw third-party data sharing); formal compliance would require a BAA with our infrastructure providers, which is a real next step, not a technical blocker.
What we learned
We learned that "AI health app" doesn't have to mean "wrap an LLM around your data" — the more defensible and genuinely useful architecture puts statistics first and treats the LLM as the last-mile translator, not the analyst, with deliberately minimal access to anything sensitive. We also learned a lot about the practical realities of wearable data (GPX extension namespace inconsistencies across providers, unit normalization, physiological plausibility bounds) that don't show up until you actually try to parse real-shaped files.
What's next for Numa
- Real wearable integration via a data aggregator (Terra, Vital, or Spike API) instead of manual CSV/GPX upload, so the ingestion layer becomes near-zero-friction
- Formal compliance work (BAAs with infrastructure providers) to move from "architected for HIPAA/GDPR principles" to certified compliance
- Cold-start handling using cohort-level priors for new users before enough personal history exists, with the UI explicitly communicating reduced confidence during that period
- Expanding correlation checks and activity types (currently running/cycling/gym) as more data patterns are validated
- A reflection-habit loop (smart, low-friction prompts after a synced workout) to keep the human-context side of the data flowing, since that's what makes the personalization engine improve over time
Built With
- bullmq
- correlation-analysis
- csv-parser
- docker
- express.js
- fitness-tracking
- groq
- health-tech
- huggingface-spaces
- llm
- machine-learning
- next.js
- node.js
- postgresql
- redis
- responsible-ai
- rest-api
- statistics
- supabase
- tailwindcss
- typescript
- websocket

Log in or sign up for Devpost to join the conversation.