Web UI SDK

The Tiro.health Web UI SDK provides framework-agnostic JavaScript components for integrating FHIR-based form filling capabilities into your web application.

Overview

The Web UI SDK is built around an imperative API using constructor functions and mount()/unmount() methods, making it compatible with any JavaScript framework or vanilla JavaScript. The SDK provides:

  • FormFiller: Interactive form filling UI with full SDC (Structured Data Capture) support
  • LaunchContextProvider: Patient context integration for pre-population
  • Narrative: Clinical narrative generation from responses
  • ValidationFeedback: Real-time form validation display
  • SDCClient: FHIR R5 SDC backend communication

All components work together seamlessly and can be mounted on any DOM element in your application.


Installation

The Web UI SDK is hosted in our private Google Artifact Registry. After your service account has been granted access, configure npm to authenticate with the registry.

Configure Registry Authentication

Option A: Using npx (recommended for initial setup)

npx google-artifactregistry-auth

Option B: Manual configuration

Add the following to your .npmrc file:

@tiro-health:registry=https://europe-npm.pkg.dev/tiroapp-4cb17/npm-ext/
//europe-npm.pkg.dev/tiroapp-4cb17/npm-ext/:always-auth=true

Install the Package

npm install @tiro-health/web-sdk

For more details on configuring authentication, see the Google Cloud Artifact Registry documentation.


Quick Start

Here's a minimal example showing how to mount a FormFiller component:

import { FormFiller } from '@tiro-health/web-sdk'

// Create FormFiller instance
const filler = new FormFiller({
  questionnaire: 'your-questionnaire-id',
  sdcEndpoint: {
    resourceType: 'Endpoint',
    address: 'https://your-sdc-backend-address/fhir'
  }
})

// Mount to a DOM element
const container = document.getElementById('form-container')
filler.mount(container)

// Later: cleanup when done
filler.unmount()

For complete framework-specific integration guides, see Framework Integration below.


Core Components

FormFiller

The primary component for rendering and managing form interactions. Handles all SDC features including conditional logic, calculations, validation, and submission.

Constructor Signature:

new FormFiller(config: {
  questionnaire: string;
  sdcEndpoint: {
    resourceType: 'Endpoint';
    address: string;
  };
  initialResponse?: QuestionnaireResponse;
  onSubmit?: (response: QuestionnaireResponse) => void;
  onChange?: (response: QuestionnaireResponse) => void;
  onError?: (error: Error) => void;
})

Methods:

  • mount(element: HTMLElement): void - Mounts the component to the specified DOM element
  • unmount(): void - Removes the component and cleans up resources

Example:

const filler = new FormFiller({
  questionnaire: 'phq-9',
  sdcEndpoint: {
    resourceType: 'Endpoint',
    address: 'https://your-sdc-backend.example.com/fhir'
  },
  onSubmit: (response) => {
    console.log('Form submitted:', response)
    // Handle submission (e.g., save to your backend)
  },
  onChange: (response) => {
    console.log('Form updated:', response)
    // Handle changes (e.g., auto-save)
  },
  onError: (error) => {
    console.error('Form error:', error)
    // Handle errors (e.g., show notification)
  }
})

const container = document.getElementById('form-container')
filler.mount(container)

For detailed API documentation, see FormFiller API Reference.

LaunchContextProvider

Provides patient context to the FormFiller for pre-populating forms with patient data. Connects to your FHIR R5 data endpoint to fetch relevant patient information.

Constructor Signature:

new LaunchContextProvider(config: {
  dataEndpoint: {
    resourceType: 'Endpoint';
    address: string;
  };
  filler: FormFiller;
  patientId?: string;
})

Methods:

  • mount(element: HTMLElement): void - Mounts the context provider
  • unmount(): void - Removes the provider and cleans up

Example:

import { FormFiller, LaunchContextProvider } from '@tiro-health/web-sdk'

const filler = new FormFiller({
  questionnaire: 'patient-intake',
  sdcEndpoint: {
    resourceType: 'Endpoint',
    address: 'https://sdc-backend.example.com/fhir'
  }
})

const contextProvider = new LaunchContextProvider({
  dataEndpoint: {
    resourceType: 'Endpoint',
    address: 'https://fhir-server.example.com/fhir'
  },
  filler: filler,
  patientId: 'patient-123'
})

// Mount both components
const contextContainer = document.getElementById('context-container')
const formContainer = document.getElementById('form-container')

contextProvider.mount(contextContainer)
filler.mount(formContainer)

For detailed API documentation, see LaunchContextProvider API Reference.

Narrative

Generates human-readable clinical narratives from QuestionnaireResponse data. Useful for displaying summaries or generating clinical notes.

Constructor Signature:

new Narrative(config: {
  filler: FormFiller;
})

Methods:

  • mount(element: HTMLElement): void - Mounts the narrative component
  • unmount(): void - Removes the component

Example:

import { FormFiller, Narrative } from '@tiro-health/web-sdk'

const filler = new FormFiller({
  questionnaire: 'clinical-assessment',
  sdcEndpoint: {
    resourceType: 'Endpoint',
    address: 'https://sdc-backend.example.com/fhir'
  }
})

const narrative = new Narrative({
  filler: filler
})

// Mount both components
filler.mount(document.getElementById('form-container'))
narrative.mount(document.getElementById('narrative-container'))

For detailed API documentation, see Narrative API Reference.

ValidationFeedback

Displays real-time validation errors and warnings as users fill out forms. Helps guide users to complete forms correctly.

Constructor Signature:

new ValidationFeedback(config: {
  filler: FormFiller;
})

Methods:

  • mount(element: HTMLElement): void - Mounts the validation feedback component
  • unmount(): void - Removes the component

Example:

import { FormFiller, ValidationFeedback } from '@tiro-health/web-sdk'

const filler = new FormFiller({
  questionnaire: 'patient-registration',
  sdcEndpoint: {
    resourceType: 'Endpoint',
    address: 'https://sdc-backend.example.com/fhir'
  }
})

const validation = new ValidationFeedback({
  filler: filler
})

// Mount both components
filler.mount(document.getElementById('form-container'))
validation.mount(document.getElementById('validation-container'))

For detailed API documentation, see ValidationFeedback API Reference.


Configuration

Endpoint Configuration

The SDK requires two types of FHIR endpoints:

SDC Endpoint (required for FormFiller)

  • Provides Questionnaire resources and processes QuestionnaireResponse submissions
  • Must be a FHIR R5 SDC-compliant endpoint
  • Used by: FormFiller component

Data Endpoint (optional, for LaunchContextProvider)

  • Provides patient context and resources for pre-population
  • Must be a FHIR R5 compliant endpoint
  • Used by: LaunchContextProvider component

Example configuration:

const sdcEndpoint = {
  resourceType: 'Endpoint',
  address: 'https://your-sdc-backend.example.com/fhir'
}

const dataEndpoint = {
  resourceType: 'Endpoint',
  address: 'https://your-fhir-server.example.com/fhir'
}

Environment Variables

For security, store endpoint URLs and sensitive configuration in environment variables:

# .env
VITE_SDC_ENDPOINT=https://your-sdc-backend.example.com/fhir
VITE_DATA_ENDPOINT=https://your-fhir-server.example.com/fhir

Then reference them in your code:

const filler = new FormFiller({
  questionnaire: 'my-form',
  sdcEndpoint: {
    resourceType: 'Endpoint',
    address: import.meta.env.VITE_SDC_ENDPOINT
  }
})

For detailed configuration options, see SDCClient API Reference.


Visualization Features

The Web UI SDK includes built-in visualization features to help developers understand component boundaries and behavior during development.

Component Borders

Add colored borders to see which components are mounted:

const filler = new FormFiller({
  questionnaire: 'my-form',
  sdcEndpoint: { /* ... */ },
  visualize: true  // Adds colored border around FormFiller
})

const narrative = new Narrative({
  filler: filler,
  visualize: true  // Adds colored border around Narrative
})

Each component type gets a distinct color:

  • FormFiller: Blue border
  • LaunchContextProvider: Green border
  • Narrative: Purple border
  • ValidationFeedback: Orange border

Toggle Button

Add a toggle button to show/hide component visualizations:

import { VisualizationToggle } from '@tiro-health/web-sdk'

const toggle = new VisualizationToggle()
toggle.mount(document.getElementById('toggle-container'))

// The toggle will control all components with visualize: true

Example with full visualization:

import {
  FormFiller,
  Narrative,
  ValidationFeedback,
  VisualizationToggle
} from '@tiro-health/web-sdk'

const filler = new FormFiller({
  questionnaire: 'my-form',
  sdcEndpoint: { resourceType: 'Endpoint', address: 'https://...' },
  visualize: true
})

const narrative = new Narrative({ filler, visualize: true })
const validation = new ValidationFeedback({ filler, visualize: true })
const toggle = new VisualizationToggle()

// Mount all components
filler.mount(document.getElementById('form'))
narrative.mount(document.getElementById('narrative'))
validation.mount(document.getElementById('validation'))
toggle.mount(document.getElementById('toggle'))

Note: Visualization features should be disabled in production builds. Use environment variables to control this:

visualize: import.meta.env.DEV

Lifecycle Management

Proper lifecycle management is crucial to prevent memory leaks and ensure clean component behavior.

Mounting Components

All components follow the same mounting pattern:

const component = new ComponentName(config)
component.mount(domElement)

Important considerations:

  • The DOM element must exist before calling mount()
  • Mounting overwrites any existing content in the element
  • You can only mount a component instance once

Unmounting Components

Always unmount components when they're no longer needed:

component.unmount()

Unmounting:

  • Removes the component's DOM elements
  • Cleans up event listeners
  • Cancels pending network requests
  • Frees up memory

Framework-Specific Cleanup

React:

useEffect(() => {
  const filler = new FormFiller(config)
  filler.mount(containerRef.current)

  return () => {
    filler.unmount()  // Cleanup on unmount
  }
}, [])

Angular:

ngOnDestroy() {
  this.filler?.unmount()  // Cleanup on destroy
}

Vanilla JavaScript:

// When removing from DOM or navigating away
window.addEventListener('beforeunload', () => {
  filler.unmount()
})

For complete lifecycle patterns, see Framework Integration.


Framework Integration

The Web UI SDK works with any JavaScript framework. Below are links to comprehensive integration guides:

React Integration

Complete guide for integrating with React applications using hooks, refs, and proper cleanup patterns.

View React Integration Guide →

Angular Integration

Complete guide for integrating with Angular applications using lifecycle hooks, ViewChild, and standalone components.

View Angular Integration Guide →

Vanilla JavaScript Integration

Complete guide for integrating with vanilla JavaScript using modern ES modules and Vite.

View Vanilla JS Integration Guide →

CDN (No Build Tools)

Quick setup for prototyping and simple applications without build tools. Load the SDK directly from CDN.

View CDN Integration Guide →


Next Steps

  • Framework Integration: Choose your framework and follow the detailed integration guide
  • API Reference: Explore the complete API documentation for each component
  • Live Examples: Check out the web-sdk-tutorial repository with working demos

For questions or support, please contact the Tiro.health team.

Was this page helpful?