ai-healthcare-app
Health Pass
- License — License: AGPL-3.0
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Community trust — 51 GitHub stars
Code Pass
- Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Pass
- Permissions — No dangerous permissions requested
No AI report is available for this listing yet.
:four_leaf_clover: Healthcare AI agent app that combines medical records with AI-assisted conversations
OpenHealth
A self-hostable health data platform that combines structured medical records with AI-assisted conversations. Upload lab results, health checkups, and personal health context — then chat with LLM providers using that data as grounded context.
Built with Next.js 15, TypeScript, PostgreSQL, and an optional Redis cache layer for production deployments.
Table of Contents
- Features
- Architecture
- Workflows
- Project Structure
- Requirements
- Installation
- Configuration
- Development
- Testing
- Troubleshooting
- Contributing
- FAQ
- License
Features
| Capability | Description |
|---|---|
| Health data ingestion | Upload PDFs and images; automatic parsing into structured JSON |
| Multi-provider LLM support | OpenAI, Anthropic, Google Gemini, and Ollama (local) |
| Privacy-first deployment | Run fully local with Docling + Ollama — no cloud required |
| Cloud mode | Managed blob storage and Trigger.dev background jobs |
| Internationalization | 10 locales via next-intl |
| Redis cache layer | Optional persistence for API response caching with graceful degradation |
| Credential encryption | AES-256-CBC for stored LLM API keys |
Architecture
flowchart TB
subgraph Client
UI[Next.js App Router UI]
end
subgraph Application
API[API Routes and Server Actions]
Auth[NextAuth Credentials]
Parser[Health Data Parser]
Cache[Cache Service]
end
subgraph Data
PG[(PostgreSQL)]
Redis[(Redis)]
end
subgraph External
Docling[Docling Serve]
LLM[LLM Providers]
Blob[Vercel Blob]
Trigger[Trigger.dev]
end
UI --> API
API --> Auth
API --> Parser
API --> Cache
Cache --> Redis
API --> PG
Parser --> Docling
Parser --> LLM
API --> Blob
API --> Trigger
Deployment modes
| Mode | Storage | Parsing | Background jobs |
|---|---|---|---|
local |
Filesystem (public/uploads) |
Docling (Docker) | In-process |
cloud |
Vercel Blob | Upstage / cloud APIs | Trigger.dev |
Workflows
Health data upload and parsing
sequenceDiagram
participant User
participant API as /api/health-data
participant Parser as PDF Parser
participant DB as PostgreSQL
participant Cache as Redis
User->>API: POST multipart file
API->>DB: Create record (status PARSING)
API->>Parser: parseHealthData()
Parser-->>API: Structured JSON + OCR metadata
API->>DB: Update record (status COMPLETED)
API->>Cache: Invalidate cached entry
API-->>User: Parsed health data
Authenticated chat session
sequenceDiagram
participant User
participant Middleware
participant Chat as /api/chat-rooms
participant LLM as Provider API
User->>Middleware: Request /chat/[id]
Middleware->>Middleware: Verify JWT session
User->>Chat: POST message
Chat->>LLM: Stream completion with health context
LLM-->>User: Assistant response
Project Structure
open-health/
├── docs/ # Engineering documentation and audit notes
├── messages/ # i18n translation files (10 locales)
├── prisma/ # Database schema, seed data, migrations
├── public/ # Static assets and local upload directory
├── src/
│ ├── actions/ # Next.js server actions
│ ├── app/ # App Router pages and API routes
│ ├── components/ # React UI components (shadcn/ui)
│ ├── context/ # React context providers
│ ├── hooks/ # Custom React hooks
│ ├── lib/
│ │ ├── api/ # API helpers (auth guards)
│ │ ├── config/ # Typed environment configuration
│ │ ├── encryption/ # AES encryption for API keys
│ │ ├── errors/ # Application error types
│ │ ├── health-data/ # Parsers (PDF, vision, document)
│ │ ├── logger/ # Structured JSON logging
│ │ └── redis/ # Connection manager and cache service
│ ├── trigger/ # Trigger.dev background tasks
│ ├── auth.ts # NextAuth configuration
│ └── instrumentation.ts # Server lifecycle hooks
├── docker-compose.yaml # Local stack: Postgres, Redis, Docling, app
├── Containerfile # Production container image
└── vitest.config.ts # Unit test configuration
Design decisions:
- Infrastructure code lives under
src/lib/with clear sub-modules - API auth guards are centralized in
src/lib/api/ - Redis is optional — the app degrades gracefully when
REDIS_ENABLED=false
Requirements
- Node.js 20+
- Docker or Podman (recommended for local stack)
- PostgreSQL 15+
- Redis 7+ (optional, enabled by default)
Installation
Quick start with Docker
git clone https://github.com/OpenHealthForAll/open-health.git
cd open-health
cp .env.example .env
# Edit .env — generate AUTH_SECRET and ENCRYPTION_KEY (see Configuration)
docker compose --env-file .env up --build
Open http://localhost:3000 and register an account.
Manual setup
npm install
cp .env.example .env
# Start PostgreSQL and Redis locally, then:
npx prisma db push
npx prisma db seed
npm run dev
Configuration
Copy .env.example to .env and configure the following:
Required
| Variable | Description |
|---|---|
DATABASE_URL |
PostgreSQL connection string |
AUTH_SECRET |
NextAuth signing secret (32+ random bytes, base64) |
ENCRYPTION_KEY |
AES-256 key for API key storage (32 bytes, base64) |
NEXT_PUBLIC_URL |
Public URL of the application |
Generate secrets:
node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"
Redis
| Variable | Default | Description |
|---|---|---|
REDIS_URL |
redis://localhost:6379 |
Redis connection URL |
REDIS_ENABLED |
true |
Set to false to disable caching |
REDIS_KEY_PREFIX |
open-health: |
Namespace prefix for cache keys |
REDIS_CONNECT_TIMEOUT_MS |
10000 |
Connection timeout |
REDIS_MAX_RETRIES |
10 |
Max retries per request |
Deployment
| Variable | Values | Description |
|---|---|---|
DEPLOYMENT_ENV |
local or cloud |
Controls storage and parser backends |
LOG_LEVEL |
debug, info, warn, error |
Logging verbosity |
Cloud-only (when DEPLOYMENT_ENV=cloud)
| Variable | Description |
|---|---|
OPENAI_API_KEY |
Platform OpenAI key |
ANTHROPIC_API_KEY |
Platform Anthropic key |
GOOGLE_API_KEY |
Platform Google key |
BLOB_READ_WRITE_TOKEN |
Vercel Blob storage |
TRIGGER_PROJECT_ID |
Trigger.dev project |
TRIGGER_SECRET_KEY |
Trigger.dev secret |
Development
npm install # Install dependencies
npm run dev # Start dev server (port 3000)
npm run typecheck # TypeScript validation
npm run lint # ESLint
npm run test # Unit tests (Vitest)
npm run validate # typecheck + lint + test
npm run build # Production build
Docker services
docker compose up database redis docling-serve # Infrastructure only
docker compose up --build # Full stack
Ollama with Docker
When running Ollama on the host machine:
- macOS:
http://docker.for.mac.localhost:11434 - Windows:
http://host.docker.internal:11434
Testing
Tests use Vitest and cover infrastructure modules:
npm run test # Run all tests once
npm run test:watch # Watch mode
Test files are co-located with source: src/**/*.test.ts
Covered areas:
- Environment configuration parsing
- Redis key building and config
- Cache service serialization
- Application error types
Troubleshooting
Build fails with encryption key error
Ensure ENCRYPTION_KEY is set in .env before running npm run dev. Generate a valid 32-byte base64 key (see Configuration).
Redis connection refused
- Verify Redis is running:
docker compose ps redis - Check
REDIS_URLmatches your environment - Disable Redis temporarily:
REDIS_ENABLED=false
PDF parsing fails locally
Confirm Docling is running:
docker compose logs docling-serve
Database schema out of sync
npx prisma db push
npx prisma generate
TypeScript errors after pulling
npm install
npx prisma generate
npm run typecheck
Contributing
- Fork the repository
- Create a feature branch:
git checkout -b feat/your-feature - Run validation before committing:
npm run validate - Open a pull request with a clear description
See CONTRIBUTING.md for detailed guidelines.
Commit conventions: Use imperative mood (feat:, fix:, chore:, docs:, test:, refactor:).
FAQ
Can I run this without Redis?
Yes. Set REDIS_ENABLED=false. The application skips caching and continues to work normally.
Is my health data sent to cloud LLMs automatically?
Only when you configure cloud LLM providers and use cloud deployment mode. Local mode with Ollama keeps inference on your machine.
What file formats are supported?
PDF, PNG, JPEG, and other image formats. PDFs are converted to images for vision-model parsing.
How are API keys stored?
LLM provider API keys are encrypted at rest using AES-256-CBC with your ENCRYPTION_KEY.
Does this replace medical advice?
No. OpenHealth is an informational tool. Always consult qualified healthcare professionals for medical decisions.
License
See LICENSE.
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found