HealthAgent turns daily Apple Health exports into a clean, opinionated health summary.
- API: Fastify + Prisma (Postgres)
- Web: Next.js App Router
- Raw storage: local disk (dev) or GCS (cloud)
- Auth: NextAuth (GitHub) with per-user ingest tokens and user-scoped data
Quick walkthrough: ONBOARDING.md.
- Daily ingest → canonical tables → metrics pack
- Optional weekly insights doc (diff-based)
- UI focused on trend + next actions
apps/api— Fastify API + Prismaapps/web— Next.js frontendstorage/local— local raw ingest storage (dev)
Prereqs: Node 20+, pnpm, Docker.
pnpm i
pnpm db:up
pnpm db:generate
pnpm db:migrate
cp apps/api/.env.example apps/api/.env
cp apps/web/.env.example apps/web/.env.local
pnpm devNotes:
- API loads dotenv from
apps/api/.env. - Set the same
INTERNAL_API_KEYandPIPELINE_TOKENin both env files. NEXTAUTH_SECRET,GITHUB_CLIENT_ID, andGITHUB_CLIENT_SECRETare required for sign-in.
This repo includes a small Health Auto Export sample. It will write the sample into local storage and run the full pipeline:
pnpm --filter @health-agent/api seed:sample
pnpm --filter @health-agent/api legacy:migrate -- --target-user-id <user-id>Then open:
- Dashboard: http://localhost:3000
- Insights: http://localhost:3000/insights
POST /api/ingest/apple-health(auth: per-userX-INGEST-TOKENorAuthorization: Bearer <token>)POST /api/pipeline/run(auth:X-INTERNAL-API-KEY+X-USER-ID, orX-PIPELINE-TOKEN+X-USER-ID)GET /api/pipeline/latest(auth:X-INTERNAL-API-KEY+X-USER-ID)GET /api/insights/latest(auth:X-INTERNAL-API-KEY+X-USER-ID)GET /api/data-quality/summary(auth:X-INTERNAL-API-KEY+X-USER-ID)
See apps/api/.env.example and apps/web/.env.example for the full lists. Common ones:
INGEST_TOKENINTERNAL_API_KEYPIPELINE_TOKENPIPELINE_MAX_INGESTS_PER_RUN(default25)API_BASE_URL(for the web app to call the API)NEXT_PUBLIC_SITE_URL(canonical web URL for metadata, sitemap, and llms.txt)NEXTAUTH_SECRET+GITHUB_CLIENT_ID+GITHUB_CLIENT_SECRET(web auth)DATABASE_URLSTORAGE_PROVIDER=local|gcs(+STORAGE_LOCAL_DIRorSTORAGE_BUCKET)INSIGHTS_ENABLED(optional, default false)OPENAI_API_KEY+INSIGHTS_MODEL(optional; only used whenINSIGHTS_ENABLED=true)INSIGHTS_OPENAI_TIMEOUT_MS/INSIGHTS_TINKER_TIMEOUT_MS(optional request timeouts, ms)TINKER_API_KEY+TINKER_MODEL_PATH(optional alternative backend for insights)- Target weight is set in the Preferences tab (used for projected timeline)
- Copy
apps/api/.env.exampletoapps/api/.envand setINSIGHTS_ENABLED=true. - Add your OpenAI key to
OPENAI_API_KEYand choose a chat-completions model forINSIGHTS_MODEL(e.g.gpt-4o-mini) inapps/api/.env. - Keep the key server-side only; the web app never needs it. Trigger insights generation by running the pipeline (
POST /api/pipeline/runwithx-internal-api-key+x-user-idheaders, or usepnpm --filter @health-agent/api seed:samplelocally). - Alternatively, set
TINKER_API_KEY(withTINKER_MODEL_PATH) to use the Tinker bridge backend.
GCP deployment (Cloud Run + GCS + Cloud Scheduler + external/serverless Postgres like Neon) is documented in DEPLOY_GCP.md.
- Cheapest: run local only.
- If cloud: prefer serverless Postgres + pay-per-use compute.
- Cloud SQL is always-on; set a billing alert if you use it.
