Self-hosted · solo build
LinkRing —
self-hosted health tracker
A WHOOP without the subscription
WHOOP charges a monthly subscription for recovery scores computed on someone else's servers. LinkRing computes them from a $30 smart ring, on hardware I control, and the data never leaves the house.
The design decision that matters: every score is measured against my own 14-day rolling baseline, not a population average. Recovery (0–100) maps the night's resting heart rate — the 5th percentile of the overnight window — against that baseline as a logistic z-score. Strain (0–21) weights the day's heart-rate minutes across five effort zones; a day at 14 or above is classified hard. Sleep duration and quality are estimated from the overnight heart-rate dip. A number only means something compared to you.
It runs like real infrastructure, not a script: two launchd services on a Mac hub — a WSGI server for the dashboard, and a 15-minute cycle that syncs the ring, recomputes scores, exports a daily report to my Obsidian vault, and rotates database backups. The dashboard reaches my phone over Tailscale; nothing is ever exposed to the public internet.
The dashboard
Each day gets an end-of-day report with a plain-language verdict — "well recovered, green light to push" or "run down — favour rest" — and a one-tap export to my Obsidian vault. Metrics the hardware can't measure yet don't show fake numbers; the card says what's missing and why.
Key decisions
- Personal rolling baseline over absolute thresholds — the scoring engine (~200 lines of NumPy/SciPy) ships with an assert-based self-check suite that runs before every deploy.
- Production discipline on a hobby project: WSGI server, launchd auto-restart, rotating logs, daily database backups with 14-generation retention.
- Reused the ring's existing open-source client instead of writing custom Bluetooth code — build the validation layer, not the plumbing.
- Obsidian vault integration: daily scores sync into my knowledge base every 15 minutes as readable notes.
- No faked metrics. HRV and SpO₂ math is written and self-tested but gated off until real-time pulse capture exists to feed it. No smart ring measures blood pressure, so LinkRing will never display one. v1 runs end-to-end today; first live ring pairing is the current step.
The whole system is about 625 lines of Python across five files, two SQLite databases, and zero cloud dependencies. It replaces a $360-a-year subscription with a $30 ring and code I can read.
v1 in production — ring pairing next