Own your health data. Vitalix reads your Health Connect records on-device and forwards them as JSON to a server you control. It ships with a self-hosted receiver that stores your health data in your own Postgres and shows it back to you on a private dashboard — no Google Sheets, no CSV; your records live on infrastructure you own.
List of data that we export and store can be check on Data Coverage
┌──────────────┐ reads ┌───────────────┐ POST /api/health ┌──────────────────┐
│ Health │ ─────────► │ Vitalix app │ ───────────────────► │ Vitalix receiver │
│ Connect │ on-device │ (Android) │ Bearer <token> │ (your server) │
└──────────────┘ └───────────────┘ └──────────────────┘
Postgres + dashboard
| Path | What it is |
|---|---|
android/ |
The Vitalix Android app (com.android.vitalix). Reads Health Connect, forwards JSON. |
web/ |
The Vitalix receiver — a self-hosted Node/Express + Postgres server that ingests, stores, and charts the data. |
android/healthexport/ |
Upstream reference clone. Read-only; not shipped. |
docs/ |
Design spec and branding. |
Reads Health Connect on-device and forwards only the metrics you enable to your server. Highlights:
- Pick exactly which of ~30 metrics to send; choose a date range or backfill history.
- Auto-sync in the background via WorkManager, gated so it only turns on once the OS will actually let it run in the background (battery-optimization exemption + OEM allow-list confirmation on aggressive vendors like Samsung).
- Server URL + optional bearer token stored in
EncryptedSharedPreferences.
Build:
cd android
./gradlew installDebug # build + install to a connected device/emulator
./gradlew testDebugUnitTest # JVM unit testsRequires a device/emulator with Health Connect installed. minSdk 30, compileSdk 36, Java 11.
A small Express app that authenticates the app, ingests the JSON payload at POST /api/health, stores per-day rows in Postgres, and serves a private dashboard.
- Endpoints:
POST /api/health(ingest, bearer-auth),GET /api/days(query),GET /healthz(liveness). - User accounts with invite codes, password reset, and an admin area (EJS views).
- Schema managed by
node-pg-migrate.
cd web
cp .env.example .env # set DATABASE_URL, JWT_SECRET, APP_BASE_URL
docker compose up # app + Postgres, migrations run on startOr without Docker (needs a running Postgres):
cd web
npm ci
npm run migrate up
npm run create-admin # create your first account
npm start # listens on :3000
npm test # unit testsPoint the Android app's server URL at https://<your-host>/api/health and paste the token from your account.
Pushes to main (and v* tags) run the tests and publish a Docker image to GitHub Container Registry via .github/workflows/web.yml:
ghcr.io/<owner>/<repo>-web:latest
Deploy that image anywhere that runs containers, supplying the same env vars as .env.example and a DATABASE_URL pointing at your Postgres. To publish, ensure GitHub Actions has package-write permission (Settings → Actions → General → Workflow permissions → Read and write).
web/.env.example documents every variable. The essentials:
| Variable | Purpose |
|---|---|
DATABASE_URL |
Postgres connection string. |
JWT_SECRET |
Long random string — signs session/auth tokens. Change this. |
APP_BASE_URL |
Public URL of the receiver (used in reset/invite links). |
SMTP_*, MAIL_FROM |
Optional. If unset, reset/invite links are logged to the server console. |
PolyForm Noncommercial License 1.0.0: free to use, modify, and share for any noncommercial purpose. Commercial use requires a separate paid license - contact me@marvello.xyz to arrange one. See LICENSE for the full text.
The upstream android/healthexport/ clone is included for reference only and is not covered by this license.