Case study · Live
PCOD Tracker
AI-parsed health logging for women with PCOD
Role
Solo — product, design, full-stack
Period
Mar 2025 · live at pcod-tracker.vercel.app
The Pitch
Type about your day in plain language. Claude extracts symptoms, mood, diet, medications, sleep, and energy into structured data — no forms, no severity sliders.
The Problem
PCOD (Polycystic Ovarian Disease) affects roughly 1 in 10 women. Managing it requires tracking a complex web of symptoms, hormones, medications, diet, exercise, mood, and menstrual cycles. Most health apps make this a chore — endless forms, dropdowns, and manual data entry.
The goal was to flip the friction: let users talk about their day in plain language and let the app figure out the rest. Also: parse lab-report PDFs automatically so nobody has to type hormone values by hand.
The Approach
Rant-first health logging
The central feature is a chat-style "Rant & Vent" screen. Users type freely — "had terrible cramps today, skipped my metformin, ate pizza for lunch, couldn't sleep until 2 a.m., feeling really anxious about everything" — no forms.
Behind the scenes, Claude parses the text and extracts structured data: symptoms (cramps, severity 4/5; insomnia, severity 3/5), medications (metformin — skipped), diet (pizza, lunch), mood (anxious), sleep (estimated 5 hours), energy (low). All of it gets saved to the right database tables.
Prompt engineering as the bottleneck
The trickiest piece was getting Claude to return strict JSON without hallucinating symptoms that weren't mentioned, while still being smart enough to infer things like sleep duration from "couldn't sleep until 2 a.m."
The system prompt is a tight schema contract with worked examples, explicit anti-patterns ("do not infer a symptom from the absence of one"), and a JSON-parseable response format. Every response is validated against a Zod schema before hitting the database. Anything that fails validation falls back to a manual entry form so the user never loses the rant.
Lab report parsing
Users upload a PDF — usually a dense hormone panel (LH, FSH, testosterone, insulin, thyroid). PDF text is extracted locally with `pdf-parse`, then Claude extracts every lab value, identifies the normal range, flags abnormals, and detects any medications mentioned in the report.
The extracted medications automatically merge into the user's existing medication list with case-insensitive deduplication. No re-entry.
Visualising patterns
Raw data is useless without patterns. The app shows: a calendar heatmap of symptom frequency and intensity by day, Recharts line graphs for hormone levels over time with normal ranges as reference bands, a 7-day medication adherence streak, and cycle history with gap analysis.
Key Decisions
Local PDF extraction, not cloud
Lab reports are sensitive. PDF text extraction happens on the server but PDFs themselves are never stored — only the structured lab values persist. The Claude API call sees the extracted text, not the PDF. Nothing is retained by the AI provider.
Fallback form on every AI call
If Claude returns malformed JSON, the user still sees their rant pre-filled into a manual form — they never lose the data. This was the difference between a demo and a tool people could actually rely on.
Rant UI over dashboards as the primary surface
Most health apps lead with a dashboard full of charts. That's backwards — users need to log before they can see patterns. Leading with the lowest-friction log flow (typing in plain language) fixes the dropout at step one.
Metrics
Prisma models
15
API routes
14
Auth
Google OAuth + credentials
AI provider
Claude
Privacy
PDFs never stored
Open source
MIT
free to self-host
Stack
App
Data & auth
AI & PDF