Skip to content

TheGrapeJuice/InsightMD

Repository files navigation

InsightMD

AI-powered clinical decision support for licensed healthcare professionals.

InsightMD is a Next.js application that gives clinicians a conversational interface for differential diagnosis, drug interaction checking, triage guidance, SOAP note generation, and FHIR R4 EMR export — all backed by a large language model fine-tuned for clinical reasoning.


Features

Clinical AI

  • Differential Diagnosis — Ranked differentials with ICD-10 codes, confidence levels, and red flags based on the patient presentation
  • Triage Recommendations — Four-level triage system (self-care / telehealth / urgent-care / er) with reasoning and timeframe
  • Clinical Scoring Tools — Automatic application of validated scores: CURB-65, Wells DVT/PE, HEART, CHADS₂-VASc, qSOFA, SOFA, PHQ-9, GAD-7, NIHSS, and more
  • Drug Interaction Checking — Real-time pair-wise interaction checks powered by the OpenFDA drug label API
  • Drug Lookup — Indications, warnings, and manufacturer information from FDA label data
  • Clinical Tags — Structured condition cards with severity, medication recommendations (drug + dose + indication), and red flags

Documentation

  • SOAP Note Generation — Convert clinician dictation, interview transcripts, or pasted notes into structured SOAP format
  • EMR Extraction — AI-driven extraction of patient info, vitals, diagnoses, labs, medications, and treatment plan from unstructured clinical text
  • Document Upload — Attach PDF, DOCX, XLSX, TXT, CSV, and other file types; content is extracted and passed to the model for analysis
  • Medical Image Analysis — Upload and analyze clinical images directly in chat

EMR Integration (FHIR R4 Sandbox)

  • FHIR R4 Export — Builds and sends a complete FHIR transaction Bundle (Patient, Encounter, Condition, Observation, DocumentReference) to any sandbox FHIR endpoint
  • Auto-Export — Automatically export structured EMR data after each SOAP note is generated
  • Connection Testing — Verify FHIR server connectivity from the settings UI
  • AES-256-GCM Encryption — Bearer tokens stored in Supabase are encrypted at rest

UX

  • Voice Input — Dictate symptoms and notes via browser-based speech transcription (Hugging Face Whisper via direct transcription route)
  • Persistent Chat History — All conversations saved to Supabase for authenticated users; switch between past consultations at any time
  • Guest Mode — Full functionality without sign-in; chat history cached in localStorage for the current session
  • Dark / Light Mode — Theme switching with next-themes
  • Animated Background — Subtle ambient animation on the landing/chat page
  • Multilingual — Detects the user's language and responds entirely in that language

Tech Stack

Layer Technology
Framework Next.js 16, React 19, TypeScript
Styling Tailwind CSS v4, Shadcn UI, Radix UI
AI Model Featherless AI — Gemma 3 27B (text + vision)
AI SDK Vercel AI SDK (ai, @ai-sdk/openai, @ai-sdk/react)
Authentication Clerk (@clerk/nextjs)
Database Supabase PostgreSQL (@supabase/supabase-js)
Voice Hugging Face Whisper (via /api/speech/transcribe)
Drug Data OpenFDA Drug Label API, RxNorm API
FHIR HAPI FHIR R4 (sandbox)
Document Parsing pdf-parse, mammoth (DOCX), xlsx (spreadsheets), jszip
Markdown Rendering react-markdown, remark-gfm
Validation Zod
Dev Tools ESLint, concurrently, Docker Compose

Project Structure

InsightMD/
├── app/
│   ├── layout.tsx                  # Root layout — Clerk, ThemeProvider, AnimatedBackground
│   ├── page.tsx                    # Main chat page
│   ├── globals.css                 # Global styles
│   ├── api/
│   │   ├── chat/route.ts           # Streaming AI chat endpoint
│   │   ├── speech/transcribe/      # Voice transcription endpoint
│   │   └── emr/
│   │       ├── export/route.ts     # FHIR R4 bundle export
│   │       ├── auto-export/route.ts# Automatic post-SOAP export
│   │       ├── settings/route.ts   # Read/write EMR settings
│   │       └── test/route.ts       # FHIR connection test
│   ├── settings/emr/               # EMR settings UI page
│   ├── sign-in/                    # Clerk sign-in
│   └── sign-up/                    # Clerk sign-up
│
├── components/
│   ├── chat/
│   │   ├── ChatInterface.tsx       # Top-level chat shell with sidebar
│   │   ├── ChatInput.tsx           # Message input with file/image/voice attach
│   │   ├── MessageList.tsx         # Scrollable message history
│   │   ├── MessageBubble.tsx       # Individual message with markdown rendering
│   │   ├── TriageBadge.tsx         # Visual triage level indicator
│   │   ├── ClinicalTagsCard.tsx    # Condition + medication + red flag cards
│   │   ├── DrugInteractionCard.tsx # Drug interaction results card
│   │   ├── ImagePreview.tsx        # Inline image preview in chat
│   │   └── VoiceButton.tsx         # Push-to-talk voice input button
│   ├── emr/
│   │   └── EMRPanel.tsx            # EMR export panel shown after SOAP extraction
│   ├── ui/                         # Shadcn UI primitives (button, card, badge, etc.)
│   ├── AnimatedBackground.tsx      # Canvas/CSS background animation
│   └── ThemeProvider.tsx           # next-themes provider wrapper
│
├── lib/
│   ├── ai/
│   │   ├── model.ts                # Featherless model configuration
│   │   ├── system-prompt.ts        # Full clinical system prompt (OPQRST, knowledge base)
│   │   ├── tools.ts                # AI tool definitions (triage, drug check, EMR extract, etc.)
│   │   ├── medical-rag.ts          # Lightweight medical reference retrieval
│   │   ├── emr-extractor.ts        # AI-powered EMR/SOAP structured extraction
│   │   └── document-extractor.ts   # File content extraction (PDF, DOCX, XLSX, etc.)
│   ├── api/
│   │   ├── openfda.ts              # OpenFDA drug label + interaction queries
│   │   └── rxnorm.ts               # RxNorm drug normalization
│   ├── emr/
│   │   ├── detection.ts            # Detect SOAP payloads vs. generation requests
│   │   ├── fast-soap-parser.ts     # Zero-AI regex SOAP parser for structured notes
│   │   ├── export-payload.ts       # Build FHIR export payload from EMR entry
│   │   ├── send-export.ts          # POST FHIR bundle to configured endpoint
│   │   └── settings-store.ts       # Read/write EMR settings from Supabase
│   ├── fhir/
│   │   └── buildBundle.ts          # Construct FHIR R4 transaction Bundle
│   ├── security/
│   │   └── encryption.ts           # AES-256-GCM encrypt/decrypt for bearer tokens
│   ├── supabase/
│   │   ├── client.ts               # Browser Supabase client
│   │   ├── server.ts               # Server-side Supabase client (SSR)
│   │   ├── admin.ts                # Service-role admin client
│   │   ├── chats.ts                # Chat + message CRUD helpers
│   │   └── migrations.sql          # Chat schema migration
│   └── utils/
│       ├── utils.ts                # Tailwind cn() helper
│       └── image-compression.ts    # Client-side image compression before upload
│
├── hooks/
│   └── useVoiceInput.ts            # React hook for browser voice recording
│
├── types/
│   ├── chat.ts                     # Chat, Message, DrugInteraction, ClinicalTags types
│   └── emr.ts                      # EMREntry, VitalSigns, Diagnosis, SOAP types
│
├── supabase/migrations/
│   ├── 001_emr_connections.sql     # EMR connections table
│   └── 002_emr_app_settings.sql    # App-level EMR settings table
│
├── test-emr/                       # Local EMR test harness (see below)
├── docs/
│   └── emr_integration.md          # EMR integration reference
├── middleware.ts                    # Clerk auth middleware
├── next.config.ts
├── tsconfig.json
└── eslint.config.mjs

Quick Start

Prerequisites

  • Node.js 18+
  • npm or yarn
  • API keys: Featherless, Clerk, Supabase
  • (Optional) Hugging Face API key for voice transcription
  • (Optional) Docker for local FHIR testing

Installation

# Clone the repository
git clone <repo-url>
cd InsightMD

# Install dependencies
npm install

# Copy and fill in environment variables
cp .env.local.example .env.local

# Run the development server
npm run dev

Open http://localhost:3000 to use the app.


Environment Variables

Create a .env.local file in the project root.

AI

# Featherless AI — https://featherless.ai/dashboard
FEATHERLESS_API_KEY=your_featherless_api_key

Authentication (Clerk)

# https://dashboard.clerk.com → API Keys
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_...
CLERK_SECRET_KEY=sk_...

Database (Supabase)

# https://supabase.com → Project Settings → API
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ...
SUPABASE_SERVICE_ROLE_KEY=eyJ...   # server-side only, never expose to the browser

Voice Transcription

# Hugging Face token for Whisper transcription
HUGGINGFACE_API_KEY=hf_...

EMR Integration

# Must decode to exactly 32 bytes — used for AES-256-GCM bearer token encryption
# Generate with: node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"
EMR_TOKEN_ENCRYPTION_KEY=your_base64_32_byte_key

Database Setup

Apply the Supabase migrations in order:

-- 1. Chat history schema
-- Run: lib/supabase/migrations.sql

-- 2. EMR connections table
-- Run: supabase/migrations/001_emr_connections.sql

-- 3. EMR app settings table
-- Run: supabase/migrations/002_emr_app_settings.sql

Or via the Supabase SQL editor, paste and run each file.


Usage

Guest Mode (no login)

  • Access the app without signing in
  • Chat history is stored in localStorage for the current browser session
  • Refreshing the page preserves your chat; opening a new chat clears it

Authenticated Users

  • Sign in with Clerk (email/password or OAuth)
  • All chats and messages are saved to Supabase
  • Access your full history from the sidebar and switch between past consultations at any time

Voice Input

  • Click the microphone button in the chat input to start recording
  • Speech is transcribed and inserted as text into the message field
  • Requires a Hugging Face API key configured in .env.local

Document / Image Upload

  • Attach files directly in the chat input (PDF, DOCX, XLSX, TXT, CSV, images, and more)
  • Document text is extracted server-side and passed to the model for analysis
  • Images are sent directly to the vision model

AI Tools

The model has access to five built-in tools that are called automatically based on context:

Tool Trigger Description
set_triage_level Every clinical assessment Sets the triage badge (self-care / telehealth / urgent-care / er) with reasoning and timeframe
generate_clinical_tags Alongside triage Produces structured condition cards with ICD-10, severity, medication recommendations, and red flags
check_drug_interactions ≥ 2 medications mentioned Queries OpenFDA label data for pairwise drug interactions
get_drug_info Specific drug question Looks up indications, side effects, and warnings from FDA labels
extract_emr Dictation / SOAP / document upload Extracts a full structured EMR entry (SOAP format) from unstructured clinical text

EMR Integration

InsightMD supports sandbox-only FHIR R4 export. It is not connected to Epic, Cerner, or any production EMR system.

Configure the FHIR Endpoint

  1. Navigate to /settings/emr
  2. Enter your FHIR Base URL (e.g. http://localhost:8080/fhir)
  3. Optionally add a Bearer Token and enable Auto-Export
  4. Click Test Connection — this calls GET {FHIR_BASE_URL}/metadata

Export Flow

When a SOAP note is generated, the app can export a FHIR R4 transaction Bundle containing:

  • Patient
  • Encounter
  • Condition (0–n)
  • Observation (0–n, vitals extracted from note)
  • DocumentReference (SOAP note + transcript as base64 attachment)

Manual export: click the export button in the EMR panel after a SOAP note is generated. Auto-export: toggle in /settings/emr; the bundle is sent automatically after each extraction.

Quick Connection Test

curl -i http://localhost:3000/api/emr/test

Local FHIR Test Harness

The test-emr/ directory contains a local test harness for validating the EMR integration end-to-end without a real FHIR server.

Option A — Lightweight Node.js server (no Docker)

node test-emr/server.js

Opens a browser UI at http://localhost:8080 that displays every exported bundle in a readable layout as they arrive. Configure the app's FHIR Base URL to http://localhost:8080/fhir.

Option B — Full HAPI FHIR server (Docker)

# Start with the app
npm run dev:emr

# Or start HAPI FHIR separately
docker compose -f test-emr/docker-compose.yml up -d

FHIR metadata endpoint: http://localhost:8080/fhir/metadata

E2E Smoke Test (PowerShell)

.\test-emr\quick-test.ps1

# Custom URLs
.\test-emr\quick-test.ps1 -AppUrl "http://localhost:3000" -FhirUrl "http://localhost:8080/fhir"

Stop the test server

docker compose -f test-emr/docker-compose.yml down
# or
npm run emr:down

Scripts

Script Description
npm run dev Start the Next.js development server
npm run dev:emr Start Next.js + HAPI FHIR (Docker) concurrently
npm run dev:emr:detached Start HAPI FHIR in background, then Next.js
npm run emr:down Stop the Docker FHIR server
npm run build Production build
npm run start Start the production server
npm run lint Run ESLint

API Endpoints

Method Path Description
POST /api/chat Streaming AI chat with tool calling
POST /api/speech/transcribe Voice audio → text transcription
POST /api/emr/export Build and send FHIR R4 bundle
POST /api/emr/auto-export Automatic export triggered post-SOAP
GET/POST /api/emr/settings Read/write EMR configuration
GET /api/emr/test Test FHIR server connectivity

Clinical Disclaimer

InsightMD is a clinical decision support tool intended exclusively for use by licensed healthcare professionals. It is not a replacement for clinical judgment.

  • All AI-generated notes are drafts and require clinician review and attestation before inclusion in official medical records
  • Medication recommendations reflect evidence-based guidelines; prescribing authority remains with the licensed clinician
  • EMR export is for sandbox/demo environments only — not for use with production patient data

License

MIT

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors