Skip to content

vintasoftware/medplum-health-card-demo

Repository files navigation

Medplum SMART Health Card Demo

A Medplum Application + Bot that issues SMART Health Cards using the FHIR Operation $health-cards-issue as defined by the Issue Verifiable Credential FHIR spec.

Uses the library kill-the-clipboard.

Demo available at https://vintasoftware.github.io/medplum-health-card-demo/

Medplum SMART Health Card Demo

Features

Patient-Facing App Features

  • Immunization Filtering: Filter patient immunizations by date range
  • QR Code Generation: Generate SMART Health Card QR codes that can be scanned by healthcare providers
  • User-Friendly Interface: Built with React Medplum components

Bot Features

  • SMART Health Card Issuance: Generate health cards for any FHIR resource type, including immunizations
  • Date Filtering: Filter resources by date using _since parameter
  • Value Set Filtering: Filter resources by specific value sets (NOTE: requires UMLS Terminology, a premium Medplum feature)

Project Structure

This is a monorepo containing two main components:

  • Bots (src/bots/): Medplum bot for SMART Health Card issuance using the FHIR Operation $health-cards-issue, built with esbuild
  • App (src/app/): Patient-facing React application for generating SMART Health Cards, built with Vite

Quick Start

# Install all dependencies (root + app workspace)
npm install

# Build everything (bots + app)
npm run build

# Build only bots
npm run build:bots

# Build only app
npm run build:app

# Run tests (for bots)
npm test

# Start app development server
npm run dev:app

Bot Deployment

If you haven't already done so, follow the instructions in this tutorial to register a Medplum project.

This project uses the Medplum CLI for bot management. Follow these steps to deploy your bot:

Initial Setup (First Time Only)

  1. Build the bot code:

    npm run build:bots
  2. Get your Project ID:

    • Navigate to your Medplum project's admin panel
    • Copy your Project ID
  3. Create the bot using Medplum CLI:

    npx medplum bot create health-cards-demo-bot <PROJECT_ID> src/bots/health-cards-demo-bot.ts dist/health-cards-demo-bot.js

    This will:

    • Create a Bot resource in Medplum
    • Add the bot to medplum.config.json
    • Create a ProjectMembership linking the bot to your project
  4. Deploy the bot code:

    npx medplum bot deploy health-cards-demo-bot
  5. Deploy the custom FHIR operation:

    npm run deploy:operation

    This creates the $health-cards-issue operation definition that links to your bot (by the name health-cards-demo-bot).

  6. Set the bot as system:

    npx medplum patch Bot/<BOT_ID> '[{"op":"add","path":"/system","value":true}]'

    Replace <BOT_ID> with the bot ID from medplum.config.json (the id field for health-cards-demo-bot). This is necessary to allow the bot to access the SHC secret key.

  7. Set the Patient user access policy for executing the custom FHIR operation:

    npx medplum post AccessPolicy "$(cat patient-access-policy.json)"

    This creates an Access Policy that allows Patient users to access the Bot and OperationDefinition resources needed to execute the health card generation bot.

  8. Configure the bot secrets:

Bot Secrets Configuration

The bot requires these secrets to be configured in Medplum:

  • SHC_ISSUER: Issuer URL for the SMART Health Cards
  • HEALTH_CARD_PUBLIC_KEY: ES256 public key
  • HEALTH_CARD_PRIVATE_KEY: ES256 private key

Get example values

You can use the public/private key pair from the example issuer https://spec.smarthealth.cards/examples/issuer. Do NOT use those values in production:

SHC_ISSUER=https://spec.smarthealth.cards/examples/issuer
HEALTH_CARD_PUBLIC_KEY={"kty": "EC","kid": "3Kfdg-XwP-7gXyywtUfUADwBumDOPKMQx-iELL11W9s","use": "sig","alg": "ES256","crv": "P-256","x": "11XvRWy1I2S0EyJlyf_bWfw_TQ5CJJNLw78bHXNxcgw","y": "eZXwxvO1hvCY0KucrPfKo7yAyMT6Ajc3N7OkAB6VYy8","crlVersion": 1}
HEALTH_CARD_PRIVATE_KEY={"kty": "EC","kid": "3Kfdg-XwP-7gXyywtUfUADwBumDOPKMQx-iELL11W9s","use": "sig","alg": "ES256","crv": "P-256","x": "11XvRWy1I2S0EyJlyf_bWfw_TQ5CJJNLw78bHXNxcgw","y": "eZXwxvO1hvCY0KucrPfKo7yAyMT6Ajc3N7OkAB6VYy8","d": "FvOOk6hMixJ2o9zt4PCfan_UW7i4aOEnzj76ZaCI9Og"}

Set Secrets in Medplum

  1. Go to the "Secrets" page in app.medplum.com
  2. Add the three secrets with the example values (see above)

Patient-Facing App Configuration

A React application that allows patients to generate SMART Health Cards from their immunization records.

Prerequisites

Before running the app, deploy the health cards bot (see Bot Deployment section above).

Set up open patient registration

To allow patients to self-register, set the patient access policy as the default.

  1. Navigate to app.medplum.com Project page and select your project.
  2. In the "Edit" tab, set the "Default Patient Access Policy" field to your patient access policy and click "Update".

For more details, see the Open Patient Registration documentation.

Set up reCAPTCHA

A reCAPTCHA configuration is required for the registration form to work.

  1. Create a new reCAPTCHA configuration to get the site key and secret key at google.com/recaptcha/admin/create.
  2. Go to app.medplum.com, go to Project, then Sites. Create a Site with domains localhost and 127.0.0.1 and set the reCAPTCHA site key and secret key.
  3. Keep the reCAPTCHA site key at hand to set it as an environment variable (see the next section).

App environment variables

Create a Client Application in your Medplum project to get the client ID and secret:

  1. Create a Client Application in your Medplum project
  2. Inside the src/app directory, copy the .env.defaults file to .env and configure the environment variables:
cd src/app
cp .env.defaults .env
  1. Add the following to your .env file:
MEDPLUM_BASE_URL=https://api.medplum.com  # or your Medplum server URL
MEDPLUM_CLIENT_ID=your-client-id
MEDPLUM_PROJECT_ID=your-project-id  # Required for patient registration
MEDPLUM_RECAPTCHA_SITE_KEY=your-recaptcha-site-key  # Required for patient registration

Install and Run

From the root directory:

# Install dependencies (installs for both bots and app)
npm install

# Start the app development server
npm run dev:app

The app runs on http://localhost:3000/

Alternatively, you can run commands directly from the app directory:

cd src/app
npm run dev

Using the App

  1. New users: Click "Sign in" and then "Register here" to create a new patient account
  2. Existing users: Sign in as a Patient user
  3. (Optional) Filter your immunizations by date
  4. Click "Generate Health Card" to create a health card with your immunizations
  5. Scan the QR code with a SMART Health Card reader app

Development

Updating the Bot

After making changes to the bot code:

# Build the updated code
npm run build:bots

# Deploy to Medplum
npx medplum bot deploy health-cards-demo-bot

$health-cards-issue API Usage

The $health-cards-issue custom FHIR Operation is implemented in the bot with these parameters:

Required:

  • subject: Patient resource reference
  • credentialType: FHIR resource type to include in the health card

Optional:

Example Request (with filters):

{
  "resourceType": "Parameters",
  "parameter": [
    {
      "name": "subject",
      "valueReference": {"reference": "Patient/patient-123"}
    },
    {
      "name": "credentialType", 
      "valueUri": "Immunization"
    },
    {
      "name": "credentialValueSet",
      "valueUri": "https://terminology.smarthealth.cards/ValueSet/immunization-covid-all"
    },
    {
      "name": "_since",
      "valueDateTime": "2023-01-01"
    }
  ]
}

Bots Development

# Code quality (for bots)
npm run check:fix

# Testing (for bots)
npm run test:watch

# Tests with coverage (for bots)
npm run test:coverage

# Linting (for bots)
npm run lint:fix

App Development

# Start development server
npm run dev:app

# Preview production build
npm run preview:app

# Linting (for app, uses Biome)
npm run lint:app:fix

Deployment to GitHub Pages

This project includes a GitHub Actions workflow to automatically deploy the patient-facing app to GitHub Pages.

Setup

  1. Enable GitHub Pages for your repository:

    • Go to your repository Settings → Pages
    • Under "Build and deployment", select "GitHub Actions" as the source
  2. Configure GitHub Secrets:

    Add the following secrets to your repository (Settings → Secrets and variables → Actions → New repository secret):

    • MEDPLUM_BASE_URL: e.g., https://api.medplum.com
    • MEDPLUM_CLIENT_ID
    • MEDPLUM_PROJECT_ID
    • MEDPLUM_RECAPTCHA_SITE_KEY
  3. Configure base path (if needed):

    If your repository is hosted at https://username.github.io/repository-name/ (not at a custom domain or root), you'll need to update the Vite config in src/app/vite.config.ts to set the base path:

    export default defineConfig({
      base: '/repository-name/',  // Add this line
      // ... rest of config
    })

Deployment

The workflow automatically deploys when you push to the main branch, or you can manually trigger it from the Actions tab in your GitHub repository.

After deployment, your app will be available at:

  • https://username.github.io/repository-name/ (for project pages)

See also

For larger FHIR bundles, prefer using SMART Health Links. The Kill the Clipboard Library also supports SMART Health Link generation and it provides a Medplum Demo project.

Reference Resources

License

MIT License - see LICENSE file for details.

Commercial Support

alt text

This project is maintained by Vinta Software. We offer design and development services for healthcare companies. If you need any commercial support, feel free to get in touch: contact@vinta.com.br

About

Open-source SMART Health Card generation demo with Medplum and kill-the-clipboard library

Topics

Resources

License

Stars

Watchers

Forks

Contributors