A personal biometric dashboard for the Google Fitbit Air — daily readiness, sleep architecture, HRV, and a few derived recommendations, self-hosted end to end.
Important
Disclaimer: Pulse is a personal project built against the Google Health API for the Fitbit Air specifically. It is not affiliated with, endorsed by, or a replacement for the official Google Health app. Derived values (readiness score, sleep score, caffeine cutoff, recommended work hours, break cadence) are simple heuristics computed from your raw biometric data — they are not clinical or medical advice. Always defer to the official app and your own judgment.
Pulse pulls your own Fitbit Air data — sleep stages, heart rate variability, resting heart rate, blood oxygen, steps, and active minutes — via the Google Health API, stores it in a self-hosted database, and turns it into a single daily view: how ready you are, how you slept, and a few concrete suggestions (caffeine cutoff, recommended work hours, break cadence) derived from that data.
It's built to be opened once a day, on your own machine, as a private instrument rather than a shipped product.
- Google OAuth sign-in, scoped only to the Health API read permissions it needs
- Daily sync pulls sleep stages, HRV, resting HR, SpO2, steps, and active minutes
- Readiness / Sleep / HRV spotlight cards with a real analog gauge arc, click-to-expand for detail
- Interactive sleep hypnogram with hover tooltips and a scrub cursor
- Multi-day trend charts, all built on visx
- Optional AI insight card — bring your own OpenAI key, generate a short daily summary + tip
- Self-hosted Convex backend (Docker), no cloud database dependency
- Automatic Google access-token refresh (no silent sync failures on expiry)
Next.js (App Router) · TypeScript · Tailwind CSS · Convex (self-hosted) · Auth.js · motion · visx · lucide-react
- Create a project at console.cloud.google.com.
- APIs & Services → Library → enable Google Health API.
- APIs & Services → OAuth consent screen → External → add yourself as a test user (keeps you out of Google's full verification review).
- Add these scopes:
googlehealth.sleep.readonly,googlehealth.activity_and_fitness.readonly,googlehealth.health_metrics_and_measurements.readonly. - APIs & Services → Credentials → Create Credentials → OAuth client ID → Web application.
- Authorized JavaScript origin:
http://localhost:3000 - Authorized redirect URI:
http://localhost:3000/api/auth/callback/google
- Authorized JavaScript origin:
- Copy the Client ID and Client Secret.
docker compose -f convex-backend/docker-compose.yml up -d
docker compose -f convex-backend/docker-compose.yml exec backend ./generate_admin_key.shCopy the printed admin key.
cp .env.local.example .env.localFill in AUTH_SECRET (openssl rand -base64 32), the Google client ID/secret from step 1, and the
Convex admin key from step 2.
npm install
npx convex dev --once # pushes the schema/functions to your self-hosted backend
npm run devOpen http://localhost:3000, sign in, and sync.
In Settings inside the app, add an OpenAI API key and enable AI insights to unlock an on-demand daily summary card. The key is stored server-side in your own Convex database and is never sent back to the browser.
src/app/ routes (dashboard, settings, demo, api)
src/components/ UI components, charts (visx), gauges
src/lib/ derived-metric heuristics, Google Health API client
convex/ schema + self-hosted database functions
convex-backend/ docker-compose for the self-hosted Convex backend
Personal project, provided as-is with no warranty. See the disclaimer above.
