Skip to the content.

EyeMatics Clinical Demonstrator (EMD)

A web-based dashboard for analysing ophthalmological research data from IVOM treatments across multiple university hospital sites. Built as a prototype demonstrator for the EyeMatics research consortium.

⚠️ Research & development use only. EMD is a research prototype and is not a medical device. It must not be used for clinical decision-making, diagnosis, treatment, or any patient-care purpose. All data shipped with the project is synthetic.

Quick Start

Clone the repo, install dependencies, then run the API and the UI in two separate shells.

Prerequisites: Node.js ≥ 20, npm ≥ 10

Shell 1 — clone & start the API:

mkdir -p ~/eyematics && cd ~/eyematics
git clone https://github.com/okohlbacher/eyematics-emd-app.git emd-app
cd emd-app
npm install
npm start

Shell 2 — start the UI:

cd ~/eyematics/emd-app
npm run dev

Open http://localhost:5173 and log in. All seeded users share the default password changeme2025!:

Username Role Password
admin admin changeme2025!
forscher1 researcher changeme2025!

Development & Production

Prerequisites: Node.js ≥ 20, npm ≥ 10

Development (two ports)

npm install
npm start &
npm run dev

API on :3000 (localhost only), Vite dev server on :5173 with HMR proxying /api:3000. Log in with admin / changeme2025! (2FA off by default; OTP 123456 when enabled).

Production (single port)

npm run build      # produces dist/
# add `server: { serveFrontend: true }` to config/settings.yaml
npm start          # Express serves UI + API on http://localhost:3000

For LAN access in production, set server.host: '0.0.0.0' in config/settings.yaml. By default the server binds to 127.0.0.1 (localhost only) for safety.

See the full credential table and login flow in docs/Benutzerhandbuch.md §2.

Reporting Feedback

Any authenticated user can submit feedback via the in-app “Report issue” dialog (sidebar → message-square icon). Each submission — including page context, user/role, timestamp, description, and an optional screenshot — is stored server-side as a JSON file in the feedback/ directory at the project root:

feedback/
  issue-2026-04-24T07-12-33-441Z_3f8a9b12.json
  issue-2026-04-24T08-47-02-118Z_a1b3c5d7.json
  ...

Sending collected feedback to the developers:

  1. Log in as admin → open Settings → scroll to “Feedback Export” → click Download. This produces a single emd-issues-<date>.json file containing every issue with screenshots inlined (base64).
  2. Alternatively, zip the whole feedback/ directory directly from the server host:
    zip -r emd-feedback-$(date +%Y-%m-%d).zip feedback/
    
  3. Send the resulting .json or .zip to the development team (email attachment or shared drive). No personal patient data is included — all patient-facing data in EMD is synthetic.

Available Scripts

Command Description
npm run dev Start the Vite development server
npm run build Type-check with TypeScript and build
npm run preview Serve the production build locally
npm run lint Run ESLint
npm run lint:fix Run ESLint with --fix (autofix where possible)
npm start Start production Express server
npm test Run full Vitest suite
npm run test:ci CI gate: skipped-test guard + full suite (619/619)
npm run test:check-skips Fail if any test is skipped without an allow-list entry
npm run knip Dead-code / unused-export scan (config: knip.json)
npm run generate-bundles Regenerate synthetic FHIR bundles for configured sites

Project Structure

emd-app/
  docs/                       # Project documentation
    Benutzerhandbuch.md        #   German user guide
    Konfiguration.md           #   Configuration reference (settings.yaml)
    Lastenheft.md              #   Requirements specification
    Pflichtenheft.md           #   Functional specification
  server/                      # Express production server (REST APIs, auth, audit)
  public/data/                 # FHIR test data bundles (JSON) + OCT images
  src/
    components/                # Reusable UI components
    components/case-detail/    # CaseDetailPage sub-components
    context/                   # React context providers (Auth, Data, Language)
    config/                    # Clinical thresholds and constants
    hooks/                     # Custom hooks (useCaseData)
    i18n/                      # Translations (de/en)
    pages/                     # Page components
    services/                  # Data loading, audit, settings, issues
    utils/                     # Shared utilities (download, dateFormat, safeJson, etc.)
    types/                     # TypeScript FHIR type definitions

Data Model

The application works with HL7 FHIR R4 bundles containing Patient, Condition, Observation, Procedure, MedicationStatement, ImagingStudy, and Organization resources. All patient data is synthetic test data.

Key Features

For detailed feature descriptions see docs/Benutzerhandbuch.md.

Configuration

Settings are stored in config/settings.yaml (outside the webroot) and editable via the Settings page (persisted server-side via PUT /api/settings).

provider: local
twoFactorEnabled: false
maxLoginAttempts: 5
otpCode: '123456'
therapyInterrupterDays: 120
therapyBreakerDays: 365
dataSource:
  type: local                   # "local" or "blaze"
  blazeUrl: http://localhost:8080/fhir

Full configuration reference: docs/Konfiguration.md.

Blaze FHIR Server (Optional)

# One-command setup (requires Docker)
./scripts/load-blaze.sh

# Then: Settings > Data Source > FHIR Server → http://localhost:8080/fhir

See docs/Konfiguration.md for manual setup and custom port options.

Technology Stack

Layer Technology
Framework React 19 + TypeScript 6
Build Vite 8
Styling Tailwind CSS 4
Charts Recharts 3
Icons Lucide React
Routing React Router 7
Server Express 5 + SQLite (better-sqlite3)
Auth JWT (bcrypt, HS256/RS256, optional Keycloak)
Data HL7 FHIR R4 (local JSON or Blaze FHIR server)

Full dependency list and vulnerability scan: BOM.md.

Sites (Test Data)

Shorthand Full Name Patients (approx.) Source
UKA Universitätsklinikum Aachen 35 curated
UKC Universitätsklinikum Chemnitz 45 generated
UKG Universitätsklinikum Greifswald 45 generated
UKL Universitätsklinikum Leipzig 45 generated
UKM Universitätsklinikum Münster 45 generated
UKT Universitätsklinikum Tübingen 30 curated

Synthetic bundles for the four generated sites are produced by npm run generate-bundles (deterministic seeded output; see scripts/generate-center-bundle.ts).

Documentation

Document Description
docs/Benutzerhandbuch.md User guide (German)
docs/Konfiguration.md Configuration reference
docs/Lastenheft.md Requirements specification
docs/Pflichtenheft.md Functional specification
docs/Anforderungsabgleich.md Requirements traceability matrix
docs/architecture.md Architecture documentation
BOM.md Bill of materials & vulnerability scan
ISSUES.md Security, code quality & duplication review

OCT Image Attribution

OCT images from the OCTID — Optical Coherence Tomography Image Retinal Database, University of Waterloo (doi:10.5683/SP/YEM3RA, doi:10.5683/SP/FLGZZE). Licensed under CC BY 4.0.

Co-Development

The design, data model, and feature scope are based on requirements developed by the EyeMatics consortium — an ophthalmology use case within Germany’s Medical Informatics Initiative, jointly run by the university hospitals of Aachen, Greifswald, Münster, and Tübingen. This project was co-developed with Claude (Anthropic), an AI assistant used for code generation, architecture design, and documentation.

License

MIT License — see LICENSE for details.