visualDx  (Demo)

VisualDx Diagnosis API Proxy

This sample application demonstrates how to use the VisualDx Diagnosis Write-Up API through a secure Next.js proxy. It handles authentication, caching, and body-location normalization automatically.

Getting Started

  1. Clone this repository and install dependencies:
  2. git clone https://github.com/VisualDx/visualdx-api-diagnosis-proxy.git
    cd visualdx-api-diagnosis-proxy
    npm install
  3. Set up your .env.local file:
  4. API_BASE_URL=https://api.visualdx.com/v1
    TOKEN_URL=https://api.visualdx.com/v1/auth/token
    CLIENT_ID=your_client_id
    CLIENT_SECRET=your_client_secret
    AUDIENCE=clinical
    CACHE_TTL=259200
    
  5. Start the development server:
  6. npm run dev
  7. Test the Diagnosis JSON endpoint:
  8. curl "http://localhost:3000/api/diagnoses/52228/101"

Endpoint Overview

GET /api/diagnoses/:diagnosisId/:viewId

  • diagnosisId – Unique ID for a diagnosis (e.g., 52228 for Psoriasis).
  • viewId – VisualDx view ID (e.g., 101 = Adult, 102 = Child).
  • textFormat (optional query param) – md or html. Defaults to md.

The API proxy normalizes VisualDx data and returns simplified JSON including metadata, authors, write-up sections, and condensed body locations from the Grouped Body Locations dataset.

{
  "id": 52228,
  "name": "Psoriasis",
  "sections": [{ "title": "Synopsis", "body": "..." }],
  "images": [
    {
      "id": 494019,
      "caption": "Scaly plaques on legs.",
      "bodyLocations": ["Leg", "Foot or toes"]
    }
  ]
}

Component Reference

🧩 CaptionedImage Component

Displays a single VisualDx image with caption, metadata, and an optional zoomable modal view. This component is reused across multiple pages.

  • Supports hover overlay (caption + body/sex info)
  • Zoom and pan support inside modal viewer

<CaptionedImage
    key={key}                  // Unique key for React lists
    imageId={img.id}           // VisualDx image ID
    caption={img.caption}      // Image caption text
    metadata={img}             // Full image metadata (e.g., bodyLocations, sex, skinType)
    blurred={false/true}       // Optional blur for sensitive content
    allImages={images}         // Full image array (enables gallery navigation)
    index={idx}                // Image index within the current gallery
/>

📋 DiagnosisDetailsPage

Displays a detailed write-up for a single diagnosis, including synopsis text, authors, and a responsive image grid. Users can apply filters to control which images are displayed.

  • Route: http://localhost:3000/diagnosis/[diagnosisId]
  • Fetches normalized JSON from the proxy endpoint
  • Sidebar filters include: Body Location, Skin Type, Severity, and Blur Sensitive options
  • Image grid uses CaptionedImage components with hover overlay and fullscreen viewer

🧠 DiagnosisSummaryComponent

A compact component used to show a small summary of a diagnosis, displaying up to 3 filtered thumbnail images and the diagnosis name.

  • Accepts data (diagnosis object) and filters (same structure as the details page)
  • Filters applied automatically — hides itself if no images match criteria
  • Commonly used in list or gallery pages to preview multiple diagnoses

<DiagnosisSummaryComponent
        data={data}                 // Diagnosis object (from API)
        filters={{                  // Filter options consistent with DiagnosisDetailsPage
          hideGenital: true,        // Hide images with genital-related body locations
          hideSevere: true,         // Hide images labeled as severe or critical
          blurSensitive: true,      // Blur sensitive images (e.g., anogenital areas)
          bodyFilters: [],          // Filter by specific body locations
          skinFilters: [],          // Filter by specific skin type values (1–6)
        }}
/>            
            

🖼 ImageGalleryPage

Displays a multi-diagnosis gallery view built with multiple DiagnosisSummaryComponent blocks. It provides a unified interface to explore multiple diagnoses side by side.

  • Route: http://localhost:3000/image-gallery
  • Fetches data for several diagnoses in parallel (IDs defined in code for demo purposes)
  • Uses shared global filters that affect all displayed diagnosis summaries simultaneously
  • Each summary internally uses CaptionedImage and shares identical filtering logic as DiagnosisDetailsPage
  • Useful for browsing, comparing, or demoing multiple diagnoses at once

Tip: In a production setting, this gallery pattern can be extended to support:

  • Search or filter by diagnosis name
  • Dynamic pagination or lazy-loading of diagnosis sets
  • Client-facing dashboards for image data exploration

Resources