Inspiration
Most of us have been in this situation: you visit a doctor after weeks of feeling off, and when they ask "so what's been going on?" — you blank. You remember the headache from Tuesday but forget the fatigue that's been dragging since last month. Symptom tracking apps exist, but they force you into dropdowns and severity sliders. Nobody wants to open a form when they feel awful.
We wanted something that felt like texting a friend — just say how you feel, and let the computer figure out the rest.
What it does
SymptomJournal is an AI-powered personal health diary. You type how you're feeling in plain English — "splitting headache since noon, maybe a 7 out of 10, and really tired" — and the app:
- Extracts structured data (symptom name, severity $s \in [1, 10]$, location, duration) using OpenAI GPT-4o-mini
- Visualises frequency on a bar chart so patterns become obvious at a glance
- Generates a daily insight — a warm, plain-English summary of how you felt today
- Runs a 30-day pattern analysis — flags symptoms appearing more than twice and suggests when to see a doctor
How we built it
| Layer | Stack |
|---|---|
| Backend | FastAPI + SQLAlchemy + SQLite |
| AI | OpenAI GPT-4o-mini |
| Auth | JWT (python-jose) + bcrypt |
| Rate limiting | SlowAPI |
| Frontend | Vite + React + Tailwind CSS |
| Charts | Recharts |
| Tests | pytest + FastAPI TestClient |
The AI extraction prompt returns a strict JSON schema. For a log entry with $n$ symptoms, we compute overall severity as:
$$\bar{s} = \frac{1}{n} \sum_{i=1}^{n} s_i$$
where $s_i$ is the severity of the $i$-th extracted symptom. This gives a single comparable score per log entry, used for trend detection.
Challenges we ran into
Dependency hell on Windows. passlib 1.7.4 is incompatible with bcrypt 5.x — the newer bcrypt removed __about__, causing a silent crash on every password hash. We replaced passlib entirely with direct bcrypt calls.
Vite proxy prefix collision. The proxy rule /log was matching /login, sending auth requests to the FastAPI backend. Renaming the endpoint to /logs fixed it instantly — but it took an embarrassingly long time to spot.
Gemini API version mismatch. The pinned google-generativeai 0.7.2 SDK uses the v1beta API, where gemini-1.5-flash no longer exists. We switched to OpenAI, which also gave us better JSON reliability and predictable pricing.
Rate limiting during tests. SlowAPI's per-endpoint @limiter.limit() decorators don't respect limiter._enabled = False. The fix was a TESTING=1 environment variable set before module import, with a rate_limit() wrapper that becomes a no-op in test mode.
Accomplishments that we're proud of
- 23/23 unit tests passing with no real API calls — all AI functions are mocked
- A prompt engineering approach that produces reliably parseable JSON from free-text with $< 1$s latency on GPT-4o-mini
- Full JWT auth flow, input validation, and rate limiting shipped in a single hackathon session
- A landing page that actually explains the product in one screen
What we learned
- Vite's proxy config does prefix matching, not exact matching — name your API routes carefully
- React Router v6 nested routes require
<Outlet />and layout routes; standalone nested<Routes>with absolute paths silently renders nothing python-josestill uses the deprecateddatetime.utcnow()— worth watching for Python 3.14 removal- GPT-4o-mini is fast enough and cheap enough to call on every keystroke if needed — roughly $0.00015 per symptom extraction
What's next for SymptomJournal
- Trend lines — plot severity $s(t)$ over time per symptom, with a simple moving average $\bar{s}k = \frac{1}{w}\sum{i=k-w}^{k} s_i$
- Doctor export — generate a one-page PDF summary of the last 30 days, formatted for a clinical visit
- Wearable sync — ingest resting heart rate and sleep data from Apple Health / Fitbit to correlate with logged symptoms
- Medication tracking — log what you took and let AI correlate relief with symptom severity drops
- Mobile app — a React Native wrapper so logging feels as natural as sending a voice note
Built With
- api
- bcrypt
- css
- fastapi
- javascript
- openai
- pydantic
- python
- python-jose
- react
- recharts
- router
- slowapi
- sqlalchemy
- sqlite
- tailwind
- vite
Log in or sign up for Devpost to join the conversation.