WearWise is a wellness coach for consumers. It syncs Apple Health and Health Connect data, scores sleep, recovery and activity, and coaches with AI grounded in the user's own metrics. It is not a medical or diagnostic tool.
It started as a Code for Bharat prototype. The original backend and frontend histories are kept under legacy/.
Work in progress. What runs today:
| Part | Folder | State |
|---|---|---|
| Product API (Fastify, Clerk auth) | apps/api |
Working: profile, consents, Clerk webhook, health check |
| Ingest service (Go) | apps/ingest |
Working: verifies Clerk tokens, stores health sample batches |
| Database schema (dbmate) | db/migrations |
Working |
| Shared schemas, metric catalog, DB client | packages/* |
Working |
| Mobile app (Expo) | apps/mobile |
Planned |
| Metrics engine, coach, reports, billing, web | Planned |
- Node 24 or newer (
.nvmrcpins 24) - pnpm 12.5.1 (
corepack enablepicks it up frompackage.json) - Go 1.27.1, for
apps/ingest - Docker, for Postgres and Redis
pnpm install
docker compose -f infra/docker-compose.dev.yml up -d --wait
cp .env.example .env
pnpm db:upThis starts Postgres (pgvector) on port 55432 and Redis on port 56379, then applies the migrations to the wearwise database. The ports are not the defaults so they do not clash with other local databases.
Add the Clerk values to .env first:
CLERK_PUBLISHABLE_KEY=pk_test_...
CLERK_SECRET_KEY=sk_test_...
CLERK_JWT_KEY="-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----"
CLERK_WEBHOOK_SIGNING_SECRET=whsec_...CLERK_JWT_KEY is your Clerk instance's JWT public key in PEM form, from the Clerk dashboard. Keep its real line breaks; an escaped \n is rejected.
Then start it:
pnpm --filter @wearwise/api devIt listens on http://localhost:3000 (change it with PORT and HOST).
| Method | Path | Auth | What it does |
|---|---|---|---|
| GET | /healthz |
none | Database check |
| GET | /v1/me |
Clerk session token | The signed in user's profile and consents; creates the user on first call |
| PATCH | /v1/me |
Clerk session token | Update the user's time zone, body {"timezone":"Asia/Kolkata"} |
| POST | /v1/consents |
Clerk session token | Record a consent, body {"kind":"health_data_processing","version":"2026-09-24"} |
| POST | /webhooks/clerk |
Clerk webhook signature | Creates and deletes users from Clerk events |
Send the session token as Authorization: Bearer <token>. Consent kinds are privacy_notice and health_data_processing.
set -a; source .env; set +a
go -C apps/ingest run ./cmd/ingestIt listens on port 8080 (change it with PORT) and reads DATABASE_URL and CLERK_JWT_KEY.
| Method | Path | What it does |
|---|---|---|
| GET | /healthz |
Database check |
| POST | /v1/samples |
Store a batch of health samples and sleep sessions |
A user can post samples only after calling the API's GET /v1/me once and recording the health_data_processing consent; until then ingest answers 403. Bodies may be gzip encoded (Content-Encoding: gzip) and are capped at 8 MiB. Resending a batch is safe: samples are keyed on their device id, so nothing is stored twice.
pnpm db:test:up
pnpm lint && pnpm typecheck && pnpm testpnpm db:test:up migrates the separate wearwise_test database; run it once, and again after adding a migration. pnpm test runs the TypeScript tests (Vitest) and the Go tests through Turborepo.
Other checks:
./infra/check-dev-stack.sh: the database and Redis setup, including a migration up, rollback, up round trip./infra/check-prod-stack.sh: builds and runs the production compose stack locallygo -C apps/ingest test -run '^$' -bench . -benchtime=20x ./internal/ingesthttp: ingest throughput benchmark
The schema changes only through SQL files in db/migrations, run by dbmate.
pnpm db:up # apply pending migrations
pnpm db:rollback # undo the last onepackages/db mirrors the schema in Drizzle for TypeScript. Never generate or run migrations with drizzle-kit.
GitHub Actions (.github/workflows/ci.yml) runs lint, typecheck and tests on every push. A green push to main then triggers a deploy of infra/compose.prod.yml through Coolify's API, once the COOLIFY_URL, COOLIFY_TOKEN and COOLIFY_APP_UUID secrets are set. Until then the deploy step is skipped. The Coolify setup checklist is in infra/CLAUDE.md.
apps/api Fastify product API
apps/ingest Go ingest service
packages/contracts request and response schemas shared by the API and its clients
packages/db Drizzle schema mirror and Postgres client
packages/metrics-catalog the health metrics WearWise understands
db/migrations dbmate SQL migrations
infra local dev stack and production compose
legacy the original Code for Bharat prototype, read only
Each module has a CLAUDE.md with what it owns, its entry points and its gotchas.