Building My Own Health Tracker with Claude Code
After the Griljor posts, I wanted to try Claude Code on something I’d use every day. So in August, Claude and I built a health tracker for me. It’s a phone-first web app that shows me my goals, logs what I eat, how I exercise, when I sleep, and what I weigh, and puts all of it on my phone.
The code is now public at github.com/vboughner/health, for anyone curious how it’s put together. As with Griljor, Claude Code wrote the code. My part was the plan, the decisions, and using the thing every day and reporting back what was annoying.
Why not a regular fitness app
The apps I’d used before didn’t fit my goals very well, well at least not all in the same app anyway, plus they had extra options I don’t care about. As this is the age of custom software, made directly to satisfy our own needs, I wanted to experiment with that. I wanted to record my goals into an app customized to with only the feature I want.
Planning before any code
The first thing I asked for was a design. Claude read the Griljor repo and this blog’s repo, to see what was already running on my VPS, and help me decide the stack, the data model, the API, the screens, and a build plan, in phases where each one ended in something I could try out.
I made a few decisions here:
- Let it be a web app on the existing VPS, not a native Android app. That means no Play Store, no APK signing, one codebase for phone and desktop, and it installs to my phone’s home screen as a link.
- Fastify and SQLite on the server, Vite and React on the front end, all TypeScript, with a
server/+web/split that is easy to work in. - USDA FoodData Central for nutrition data, because it’s strongest on the whole and raw foods my diet is mostly made of, and you can get a free API key.
- A real login from day one, with
user_idon every table, since it would sit on a public domain, and I’ll probably want to invite other people to try it.
The first version, with food logging, exercise, weight, sleep, the combined day summary, trend charts and PWA install, came together in early August. After that, almost every new feature followed the same pattern: a short design spec, a plan broken into tasks, and implementation. Those specs and plans are all in docs/superpowers/ if you want to see how each feature was talked about before it was built.
What using it changed
Most of the changes came from a week or two of using it.
Sleep is two buttons, Up and Down. Each one stamps the current time. Pressing Up or Down again just overwrites it, which is useful when I think I’m getting into bed, and don’t actually settle for another half hour.
The goals can be read out loud to me. Reading the plan every morning is harder on tired eyes than I expected, so instead I can record myself reading it once, and play it back from the Goals page. The audio lives as a file beside the database.
The day turns over at 4am. Between midnight and 4am the screen stays on the evening I’m still in, honestly labelled “Yesterday.” Building that turned up a second bug: the app’s idea of “today” was computed on render, and nothing re-renders a phone sitting on a nightstand overnight, so it wasn’t turning over at midnight and in the morning still had yesterday’s stuff and said “Today”. Had to fix that.
Settings moved from the phone to the account. They started out stored per-device. I changed that later, because for my single account, I should get just one set of settings, the same on every device.
Deploying it on the VPS, next to Griljor
It went live on August 16th, on the same Hetzner VPS that runs Griljor, and most of the deploy notes were inherited from the game’s deployment notes.
The one new thing was that this is the first app on that server holding data that exists nowhere else. I turned on filesystem backups for the VPS, because the SQLite database and the audio recordings live outside the repo.
Reflections from building it
Looking at the screen really catches what needs to be tested and tasted. There are a little over 500 tests, and all that arithmetic lives in pure functions tested without a server or a database. Even so, after the kinds of bugs I found, Claude now checks UI changes with Playwright, driving real Chrome at phone size, and takes screenshots against a throwaway seeded account to see how well it’s working.
Writing down why things were broken helps in the future. The CLAUDE.md in the repo has a long section called “Things that are subtle — read before changing them.” Each entry is something that was wrong once, or was nearly changed for a reasonable-sounding reason, with the why next to it.
A tool built around one plan can stay small. Because there’s no general audience, a lot of things didn’t have to exist at first. There’s no signup page, no onboarding, no settings for things that are hard-coded because that’s the way I like it.
The app is on my phone’s home screen, and I use it every day. The code is at github.com/vboughner/health — the README covers running it locally when developing it. Fee free to fork the repository and make it your own. Or wait a little bit, because soon I’ll update it so that other people can create accounts on the running version on VPS so they can try it out (without having to set it all up).