HealthLog Logo

HealthLog

Your health data belongs to you. Track it on your own terms.

License: AGPL-3.0 TypeScript Next.js 16 Self-Hosted PRs Welcome

A self-hosted, privacy-first health tracking PWA.
Weight, blood pressure, mood, medications, AI insights -- all under your control.

Website · Live Demo · Documentation

--- ## Why HealthLog? Most health apps lock your data behind proprietary clouds, push subscriptions, and sell your metrics to advertisers. HealthLog takes a different approach: your data stays on your server, encrypted at rest, accessible only to you. --- ## Key Features **Health Metrics** -- Track weight, blood pressure, pulse, body fat, sleep, and steps with interactive trend charts, moving averages, and traffic-light ranges based on ESC/ESH 2018 guidelines. **Mood Logging** -- 5-point scale with tags, notes, and trend analytics. Syncs automatically from moodLog.app via webhook. **Medication Compliance** -- Flexible scheduling with time windows, recurrence patterns, intake logging (take/skip/snooze), and compliance heatmaps. External API for iOS Shortcuts integration. **Withings Integration** -- OAuth2 device sync for scales, blood pressure monitors, and activity trackers with automatic deduplication. **AI-Powered Insights** -- Bring your own OpenAI API key. Personalized analysis across blood pressure, weight, pulse, mood, BMI, and medication adherence. Cached daily to minimize API usage. **Doctor Report PDF Export** -- Generate professional medical reports client-side. European format with vital sign summaries, BP/BMI classification, compliance rates, and optional AI analysis. **PWA with Offline Support** -- Installable on iOS and Android. Service worker with intelligent caching strategies for reliable offline access. **Multi-Channel Notifications** -- Telegram (with inline action buttons), ntfy (self-hostable), and Web Push. Medication reminders with late/missed escalation. **Gamification** -- 30+ persistent achievements across intake streaks, compliance milestones, and healthy metric streaks. **Internationalization** -- Full German and English UI with 1000+ translation keys. Browser-based locale detection with per-user override. --- ## Quick Start ```bash git clone https://github.com/MBombeck/HealthLog.git cd HealthLog cp .env.example .env ``` Generate the required secrets: ```bash openssl rand -hex 32 # SESSION_SECRET openssl rand -hex 32 # ENCRYPTION_KEY openssl rand -hex 32 # API_TOKEN_HMAC_KEY ``` Add them to `.env`, then: ```bash docker compose up -d ``` Open **http://localhost:3000**. The first registered user becomes admin. --- ## Tech Stack | Layer | Technology | |-------|-----------| | Framework | Next.js 16 (App Router, React Server Components) | | Language | TypeScript (strict mode) | | Database | PostgreSQL 16 + Prisma 7 (22 models) | | Job Queue | pg-boss 12 (reminders, insights, backups) | | UI | shadcn/ui, Tailwind CSS 4, Radix UI, Lucide Icons | | Charts | Recharts 3 | | Data Fetching | TanStack Query 5 | | Forms | React Hook Form 7 + Zod 4 | | Auth | SimpleWebAuthn 13, Argon2id | | Notifications | Telegram Bot API, ntfy, Web Push (VAPID) | | PDF | jsPDF (client-side generation) | | Testing | Vitest 4 | | Deployment | Docker (multi-stage Alpine) | --- ## Security and Privacy HealthLog is designed for people who take data ownership seriously. - **Self-hosted** -- Your data never leaves your server. No telemetry, no third-party tracking. - **AES-256-GCM encryption** -- All stored secrets (OAuth tokens, API keys, VAPID keys) are encrypted at rest. - **Passkey authentication** -- WebAuthn as primary auth with password fallback (Argon2id + zxcvbn strength validation). - **Server-side sessions** -- PostgreSQL-backed with 30-day sliding expiry, HttpOnly/SameSite=Strict cookies. - **Security headers** -- CSP with nonces, HSTS, X-Frame-Options DENY, Permissions-Policy, Referrer-Policy. - **Rate limiting** -- Sliding window on auth and API endpoints. - **HMAC-SHA256 API tokens** -- Bearer tokens are hashed before storage. - **Audit logging** -- All sensitive operations tracked with IP addresses. --- ## Environment Variables ### Required | Variable | Description | |----------|-------------| | `DATABASE_URL` | PostgreSQL connection string | | `SESSION_SECRET` | 64-char hex string for session signing | | `ENCRYPTION_KEY` | 64-char hex string for AES-256-GCM | | `API_TOKEN_HMAC_KEY` | 64-char hex string for API token hashing | ### Optional | Variable | Description | |----------|-------------| | `NEXT_PUBLIC_APP_URL` | Public-facing URL (default: `http://localhost:3000`) | | `WITHINGS_CLIENT_ID` | Withings OAuth2 client ID | | `WITHINGS_CLIENT_SECRET` | Withings OAuth2 client secret | | `WITHINGS_REDIRECT_URI` | OAuth callback URL | | `WITHINGS_WEBHOOK_SECRET` | Webhook URL hardening secret | | `TELEGRAM_WEBHOOK_SECRET` | Telegram bot webhook secret | Telegram bot token, ntfy settings, Web Push VAPID keys, Umami, and GlitchTip URLs are configured in the **Admin Panel** and stored encrypted in the database. --- ## Architecture ``` src/ ├── app/ # Next.js App Router pages & API routes │ ├── api/ # REST API endpoints (~60 route files) │ ├── admin/ # Admin panel │ ├── medications/ # Medication management │ ├── measurements/ # Health metric entry │ ├── insights/ # AI-powered analytics │ ├── achievements/ # Gamification page │ ├── onboarding/ # 4-step guided setup │ └── settings/ # User preferences ├── components/ │ ├── ui/ # shadcn/ui primitives │ ├── layout/ # Shell (sidebar, topbar, bottom nav) │ ├── medications/ # Medication cards, forms, timeline │ ├── measurements/ # Measurement form, list │ ├── mood/ # Mood form, mood list │ └── charts/ # Recharts wrappers ├── lib/ │ ├── auth/ # Session, audit, passkey logic │ ├── notifications/ # Dispatcher + channel senders │ ├── jobs/ # pg-boss worker │ ├── analytics/ # Trend calculations, compliance │ ├── withings/ # OAuth client, sync service │ ├── i18n/ # Translations context & config │ ├── validations/ # Shared Zod schemas │ ├── crypto.ts # AES-256-GCM encrypt/decrypt │ ├── db.ts # Prisma singleton │ └── doctor-report-pdf.ts # Client-side PDF generation ├── hooks/ # React hooks └── generated/prisma/ # Generated Prisma client ``` ### Key Patterns - **RSC by default** -- `"use client"` only for interactive components - **API envelope** -- All responses follow `{ data, error, meta }` shape - **Encrypted secrets** -- Withings tokens, API keys, VAPID keys, notification credentials - **Timezone-aware** -- `Europe/Berlin` for display, UTC in database - **Route protection** -- `proxy.ts` checks session cookie, redirects unauthenticated requests - **Client-side PDF** -- Doctor reports generated in browser via jsPDF --- ## API Reference All mutations require authentication via session cookie. External ingest uses Bearer tokens.
Health Data | Method | Endpoint | Description | |--------|----------|-------------| | `GET` | `/api/measurements` | List measurements (paginated, filterable) | | `POST` | `/api/measurements` | Create measurement | | `DELETE` | `/api/measurements/:id` | Delete measurement | | `GET` | `/api/analytics` | Trend summaries (7d/30d) | | `GET` | `/api/export` | Export as CSV or JSON | | `POST` | `/api/import` | Import from JSON | | `POST` | `/api/doctor-report` | Aggregated data for PDF |
Mood | Method | Endpoint | Description | |--------|----------|-------------| | `GET` | `/api/mood-entries` | List mood entries | | `POST` | `/api/mood-entries` | Create mood entry | | `DELETE` | `/api/mood-entries/:id` | Delete mood entry | | `GET` | `/api/mood/analytics` | Mood trend analytics | | `POST` | `/api/integrations/moodlog/webhook` | moodLog.app webhook |
Medications | Method | Endpoint | Description | |--------|----------|-------------| | `GET` | `/api/medications` | List all medications | | `POST` | `/api/medications` | Create medication | | `PUT` | `/api/medications/:id` | Update medication | | `DELETE` | `/api/medications/:id` | Delete medication | | `POST` | `/api/medications/:id/intake` | Log intake event | | `GET` | `/api/medications/:id/compliance` | Compliance stats | | `POST` | `/api/ingest/medication` | External intake (Bearer) |
Auth and Integrations | Method | Endpoint | Description | |--------|----------|-------------| | `POST` | `/api/auth/register` | Create account | | `POST` | `/api/auth/login` | Password login | | `POST` | `/api/auth/logout` | Destroy session | | `GET` | `/api/auth/me` | Current user profile | | `POST` | `/api/auth/passkey/*` | WebAuthn flows | | `GET` | `/api/withings/connect` | Initiate Withings OAuth | | `POST` | `/api/insights/generate` | Regenerate AI insights | | `GET` | `/api/gamification/achievements` | Achievement progress | | `GET` | `/api/health` | Docker health check |
--- ## Integrations | Integration | Setup | Purpose | |-------------|-------|---------| | **Withings** | Env vars | Auto-sync weight, BP, and activity | | **Telegram** | Admin Panel | Medication reminders with inline buttons | | **ntfy** | User Settings | Self-hosted push notifications | | **Web Push** | Admin Panel | Browser-native VAPID notifications | | **OpenAI** | User Settings | AI health insights (BYOK) | | **moodLog.app** | User Settings | Mood tracking sync | | **Umami** | Admin Panel | Privacy-friendly analytics | | **GlitchTip** | Admin Panel | Sentry-compatible error tracking | --- ## Local Development ```bash # Prerequisites: Node.js 20+, pnpm, PostgreSQL cp .env.example .env pnpm install pnpm db:generate pnpm db:migrate pnpm dev ``` ### Scripts ```bash pnpm dev # Development server pnpm build # Production build pnpm lint # ESLint pnpm typecheck # TypeScript strict check pnpm test # Vitest pnpm format # Prettier pnpm db:generate # Generate Prisma client pnpm db:migrate # Create & apply migration pnpm db:migrate:deploy # Apply migrations (production) pnpm db:studio # Prisma Studio GUI ``` --- ## Deployment The included `docker-compose.yml` runs the app and PostgreSQL. The entrypoint automatically waits for the database, runs pending migrations, and starts the server. The app listens on port **3000**. Place it behind Nginx, Caddy, or Traefik for TLS termination. Works out of the box with [Coolify](https://coolify.io/). --- ## Contributing Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines. - Code style: `pnpm format && pnpm lint` - Type safety: `pnpm typecheck` must pass - Tests: `pnpm test` - UI language: German. Code, comments, and commits: English. --- ## License HealthLog is licensed under the [GNU Affero General Public License v3.0](LICENSE). ---

healthlog.dev · Live Demo · Docs