> ## Documentation Index
> Fetch the complete documentation index at: https://omniloy.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# JavaScript

> SofIA SDK integration with native JavaScript

This guide shows how to integrate SofIA SDK in applications using native JavaScript without additional frameworks.

## Initial setup

### 1. Installation

```bash theme={null}
npm install @omniloy/sofia-sdk
```

### 2. Component import

```html theme={null}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SofIA SDK - Vanilla JS</title>
    
    <!-- Import component -->
    <script type="module">
        import '@omniloy/sofia-sdk';
    </script>
</head>
<body>
    <!-- Component will be available here -->
</body>
</html>
```

## Basic implementation

### HTML structure

```html theme={null}
<div id="sofia-container">
    <!-- language="en" for English UI, default is "es" (Spanish) -->
    <sofia-sdk
        id="sofia"
        apikey="your-api-key"
        userid="user_12345"
        patientid="patient_67890"
        templateid="clinical-notes-v1"
        language="en"
        isopen="false"
        template='{
            "$schema": "http://json-schema.org/draft-07/schema#",
            "title": "clinical_notes",
            "type": "object",
            "required": ["diagnosis"],
            "properties": {
                "diagnosis": {"type": "string", "description": "Main diagnosis"}
            }
        }'
    ></sofia-sdk>
    
    <button id="toggle-sofia">Open/Close SofIA</button>
</div>
```

### JavaScript configuration

```javascript theme={null}
// Wait for component to be defined
customElements.whenDefined('sofia-sdk').then(() => {
    const sofiaComponent = document.getElementById('sofia');
    const toggleButton = document.getElementById('toggle-sofia');
    
    // Configure callback to receive reports
    sofiaComponent.handleReport = (report) => {
        console.log('Clinical report received:', report);
        
        // Process report according to your needs
        displayReport(report);
        sendToEHR(report);
    };
    
    // Configure callback for visibility changes
    sofiaComponent.setIsOpen = (isOpen) => {
        console.log('Component state:', isOpen ? 'Open' : 'Closed');
        sofiaComponent.isopen = isOpen;
        toggleButton.textContent = isOpen ? 'Close SofIA' : 'Open SofIA';
    };
    
    // Handle button click
    toggleButton.addEventListener('click', () => {
        const currentState = sofiaComponent.getAttribute('isopen') === 'true';
        sofiaComponent.setAttribute('isopen', String(!currentState));
    });
});

// Function to display report in interface
function displayReport(report) {
    const reportContainer = document.getElementById('report-display');
    if (reportContainer) {
        const heading = document.createElement('h3');
        heading.textContent = 'Clinical Report';
        const pre = document.createElement('pre');
        pre.textContent = JSON.stringify(report, null, 2);
        reportContainer.replaceChildren(heading, pre);
    }
}

// Function to send to EHR/HIS system
function sendToEHR(report) {
    // Implement integration with your system
    fetch('/api/clinical-reports', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify(report)
    }).then(response => {
        console.log('Report sent to EHR:', response.status);
    }).catch(error => {
        console.error('Error sending report:', error);
    });
}
```

## Retrieving the last report

Use the `set-get-last-report` callback to access the last generated report for the current patient/user session. The SDK provides a function that returns a `Promise` resolving to the stored report (or `undefined` if none exists).

```javascript theme={null}
sofiaComponent.setGetLastReport = (getLastReportFn) => {
    // Store the function for later use
    window.getLastSofiaReport = getLastReportFn;
};

// Later, retrieve the last report
async function fetchLastReport() {
    const report = await window.getLastSofiaReport();
    if (report) {
        console.log('Last report:', report);
    }
}
```

<Tip>
  Add `debug="true"` to the `<sofia-sdk>` element to enable verbose console logging. This is helpful during development to trace SDK lifecycle events, connection status, and configuration validation.

  ```html theme={null}
  <sofia-sdk debug="true" ...></sofia-sdk>
  ```
</Tip>

## State management

### Visibility control

```javascript theme={null}
const sofiaComponent = document.querySelector('sofia-sdk');

// Open programmatically
function openSofia() {
    sofiaComponent.isopen = true;
}

// Close programmatically  
function closeSofia() {
    sofiaComponent.isopen = false;
}

// Toggle state
function toggleSofia() {
    const isCurrentlyOpen = sofiaComponent.getAttribute('isopen') === 'true';
    sofiaComponent.setAttribute('isopen', String(!isCurrentlyOpen));
}
```

### Patient data update

```javascript theme={null}
// Update patient information
function updatePatientData(newPatientId, patientInfo) {
    sofiaComponent.patientid = newPatientId;
    sofiaComponent.patientdata = JSON.stringify(patientInfo);
}

// Usage example
updatePatientData('patient_98765', {
    fullName: 'Jane Doe',
    birthDate: '1979-03-15',
    extraData: {
        medical_practice: 'Internal Medicine',
        allergies: ['Penicillin'],
        chronic_conditions: ['Type 2 diabetes', 'Hypertension']
    }
});
```

See [Patient Data](/sofia/en/sdk/patient-data) for the complete data structure reference.

## Error handling

The SDK logs all errors to the browser console with the `[Sofia SDK]` prefix. Enable `debug="true"` to see detailed error output. Handle errors in your callbacks with standard try/catch:

```javascript theme={null}
sofiaComponent.handleReport = (report) => {
    try {
        // Process the report
        sendToEHR(report);
    } catch (error) {
        console.error('Error processing report:', error);
        // Show fallback UI to the user
    }
};
```

For a complete list of error messages and their resolution steps, see the [Error Reference](/sofia/en/sdk/error-reference).

## Complete example

For a complete and functional implementation, check our GitHub example:

**[View complete Vanilla TypeScript example →](https://github.com/Omniloy/sofia-sdk-examples/tree/main/examples/vanilla-ts)**

The example includes:

* Complete project setup
* Advanced state management
* Integration with mocked APIs
* Robust error handling
* Custom CSS styling

## Component lifecycle

### Adding the component

Wait for the custom element to be defined before configuring callbacks:

```javascript theme={null}
customElements.whenDefined('sofia-sdk').then(() => {
  const sofia = document.querySelector('sofia-sdk');
  sofia.handleReport = handleReport;
});
```

### Removing the component (SPA cleanup)

If your application dynamically adds and removes SofIA (e.g., client-side routing), remove the element from the DOM when navigating away:

```javascript theme={null}
function destroySofia() {
  const sofia = document.querySelector('sofia-sdk');
  if (sofia) {
    sofia.remove();
  }
}
```

The SDK cleans up internal resources (WebSocket connections, audio streams) automatically when the element is disconnected from the DOM.

## Additional considerations

### Performance

* The component initializes lazily to optimize loading time
* Use `customElements.whenDefined()` to avoid race conditions

### Security

* Never expose your `apikey` in client code in production
* Implement server-side validation for all reports
* Always use HTTPS for all communications

## Next steps

1. [React integration](/sofia/en/sdk/react)
2. [Angular integration](/sofia/en/sdk/angular)
3. [Required properties reference](/sofia/en/sdk/required-properties)
4. [Optional properties reference](/sofia/en/sdk/optional-properties)
