Skip to content

corticph/embedded-web

Repository files navigation

Corti Embedded Web Component

A web component and React component library that provides an embedded interface for Corti AI assistant.

Features

  • Web Component & React: Available as both a native web component and React component
  • Show/Hide: Control the visibility of the chat interface
  • Authentication Support: Built-in authentication message handling
  • TypeScript Support: Full TypeScript definitions included

Installation

npm install @corti/embedded-web

The package provides a web component by default. For React usage, also install React as a peer dependency:

npm install react @types/react

Usage

Web Component

<corti-embedded
  id="corti-component"
  base-url="https://assistant.eu.corti.app" <!-- REQUIRED -->
></corti-embedded>
const myComponent = document.getElementById('corti-component');

const userResponse = await myComponent.auth({...});

const interaction = await myComponent.createInteraction({
  "assignedUserId": null,
  "encounter": {
    "identifier": `encounter-${Date.now()}`,
    "status": "planned",
    "type": "first_consultation",
    "period": {
      "startedAt": "2025-11-11T16:14:59.923Z"
    }
  }
});

await myComponent.configureSession({"defaultTemplateKey": "soap_note"});
await myComponent.addFacts([{"text": "Chest pain", "group": "other"}]);
await myComponent.navigate('/interactions/123');
await myComponent.show()

React Component

import React, { useRef } from 'react';
import {
  CortiEmbeddedReact,
  type CortiEmbeddedReactRef,
  useCortiEmbeddedApi,
  useCortiEmbeddedStatus,
} from '@corti/embedded-web/react';

function App() {
  const cortiRef = useRef<CortiEmbeddedReactRef>(null);
  const api = useCortiEmbeddedApi(cortiRef);
  const { status } = useCortiEmbeddedStatus(cortiRef);

  const handleReady = () => {
    console.log('Corti component is ready!');
  };

  const handleEvent = (
    event: CustomEvent<{ name: string; payload: unknown }>,
  ) => {
    console.log('Event name:', event.detail.name);
    console.log('Event payload:', event.detail.payload);
  };

  const handleAuth = async () => {
    try {
      const user = await api.auth({
        access_token: 'your-token',
        token_type: 'Bearer',
        // ... rest of the token response
      });
      console.log('Authenticated:', user);

      await api.configureSession({ defaultTemplateKey: 'soap_note' });
      await api.createInteraction({
        encounter: {
          identifier: `encounter-${Date.now()}`,
          status: 'planned',
          type: 'first_consultation',
          period: { startedAt: new Date().toISOString() },
        },
      });
    } catch (error) {
      console.error('Auth failed:', error);
    }
  };

  return (
    <div style={{ height: '100vh' }}>
      <button onClick={handleAuth}>Authenticate</button>

      <CortiEmbeddedReact
        ref={cortiRef}
        baseURL="https://assistant.eu.corti.app" // REQUIRED
        visibility="visible"
        onReady={handleReady}
        onEvent={handleEvent}
        onError={event => console.error('Embedded error:', event.detail)}
        style={{ width: '100%', height: '500px' }}
      />

      <pre>{JSON.stringify(status, null, 2)}</pre>
    </div>
  );
}

Show/Hide the Component

const component = document.getElementById('corti-component');

// Show the chat interface
component.show();

// Hide the chat interface
component.hide();

API methods (recommended)

  • Use these named helpers for common tasks. They provide clearer intent and sensible defaults.

auth

const authResponse = await component.auth({
  // Example: Keycloak-style token + mode
  access_token: 'YOUR_JWT',
  token_type: 'Bearer',
  mode: 'stateful',
  ...
});

configureSession

await component.configureSession({
  defaultLanguage: 'en',
  defaultOutputLanguage: 'en',
  defaultTemplateKey: 'discharge-summary',
  defaultMode: 'virtual',
});

addFacts

await component.addFacts([
    { text: 'Patient reports chest pain', group: 'subjective' },
    { text: 'BP 120/80', group: 'vitals' },
  ],

navigate

await component.navigate('/interactions/123');

createInteraction

const created = await component.createInteraction({
  assignedUserId: null,
  encounter: {
    identifier: 'enc-123',
    status: 'in-progress',
    type: 'consult',
    period: { startedAt: new Date().toISOString() },
    title: 'Visit for cough',
  },
  patient: {
    identifier: 'pat-456',
  },
});

startRecording / stopRecording

await component.startRecording();
// ... later
await component.stopRecording();

getStatus (debugging)

console.log(component.getStatus());

Architecture

The component uses a PostMessageHandler utility class that:

  • Manages message listeners and cleanup
  • Tracks pending requests with unique IDs
  • Handles response correlation
  • Ensures proper cleanup on component destruction

React Component Features

The React component (CortiEmbeddedReact) is available as an additional export and provides:

  • Hook-based API access: useCortiEmbeddedApi(ref) exposes instance-bound methods (auth, navigate, createInteraction, etc.)
  • Generic event stream: onEvent receives all embedded events as { name, payload }
  • Status hook: useCortiEmbeddedStatus(ref) keeps latest status/reactive state
  • Multi-instance safety: API methods are scoped to the ref you pass
  • React Props: Standard React props like className, style, etc.

React Component Import

import {
  CortiEmbeddedReact,
  CortiEmbedded, // Web component also available
  type CortiEmbeddedReactRef,
  useCortiEmbeddedApi,
  useCortiEmbeddedStatus,
} from '@corti/embedded-web/react';

Event Listener Setup

  • Use onEvent for all embedded events.
  • Event detail shape is { name: string; payload: unknown }.
  • Full event catalog and payload details are documented at:
<CortiEmbeddedReact
  baseURL="https://assistant.eu.corti.app"
  onEvent={event => {
    console.log(event.detail.name, event.detail.payload);
  }}
  onReady={() => console.log('Ready')}
  onError={event => console.error(event.detail)}
/>

API Methods (React)

Use the API hook with the same component ref:

import React, { useRef } from 'react';
import {
  CortiEmbeddedReact,
  type CortiEmbeddedReactRef,
  useCortiEmbeddedApi,
} from '@corti/embedded-web/react';

function Example() {
  const ref = useRef<CortiEmbeddedReactRef>(null);
  const api = useCortiEmbeddedApi(ref);

  const run = async () => {
    await api.auth({ access_token: '...', token_type: 'Bearer', mode: 'stateful' });
    const created = await api.createInteraction({ encounter: { ... } });
    await api.navigate(`/session/${created.id}`);
  };

  return (
    <>
      <button onClick={() => void run()}>Run</button>
      <CortiEmbeddedReact ref={ref} baseURL="https://assistant.eu.corti.app" />
    </>
  );
}

For detailed React usage examples, see docs/react-usage.md.

Package Structure

  • Default export: Web component only (dist/web-bundle.js)
  • React export: Web component + React component (@corti/embedded-web/react)
  • No dependencies: Web component bundle has zero external dependencies
  • Peer dependencies: React components require React as peer dependency only

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •