> ## Documentation Index
> Fetch the complete documentation index at: https://cloud-docs.mentra.glass/llms.txt
> Use this file to discover all available pages before exploring further.

# Event Handlers

> Handle real-time events from glasses and user interactions

## Overview

Events are the primary way your app receives data from the glasses. All event handlers are accessed through `session.events`.

## Available Events

### Transcription Events

```typescript theme={null}
// Default language (en-US)
session.events.onTranscription((data) => {
  console.log(`Text: ${data.text}`);
  console.log(`Final: ${data.isFinal}`);
  console.log(`Language: ${data.transcribeLanguage}`);
});

// Specific language
session.events.onTranscriptionForLanguage('es-ES', (data) => {
  console.log(`Spanish text: ${data.text}`);
});
```

<Card title="TranscriptionData fields" icon="microphone">
  * `text`: The transcribed text
  * `isFinal`: Whether this is a final or interim result
  * `transcribeLanguage`: Language code (e.g., 'en-US')
  * `startTime`: Timestamp when speech started
  * `endTime`: Timestamp when speech ended
  * `confidence`: Confidence score (0-1)
  * `provider`: Transcription provider used
</Card>

### Button Events

```typescript theme={null}
session.events.onButtonPress((data) => {
  console.log(`Button: ${data.buttonId}`);
  console.log(`Type: ${data.pressType}`);
});
```

<Card title="ButtonPress fields" icon="hand-pointer">
  * `buttonId`: Button identifier (e.g., 'main')
  * `pressType`: 'short' or 'long'
</Card>

### Head Position Events

```typescript theme={null}
session.events.onHeadPosition((data) => {
  if (data.position === 'up') {
    console.log('User looked up');
  } else if (data.position === 'down') {
    console.log('User looked down');
  }
});
```

### Photo Events

```typescript theme={null}
session.events.onPhotoTaken((data) => {
  console.log(`Photo received: ${data.mimeType}`);
  // data.photoData is an ArrayBuffer
  processPhoto(data.photoData);
});
```

### Location Events

```typescript theme={null}
// First subscribe to location updates
session.location.subscribeToStream({}, (data) => {
  console.log(`Location: ${data.lat}, ${data.lng}`);
  if (data.accuracy) {
    console.log(`Accuracy: ${data.accuracy} meters`);
  }
});
```

### Phone Notifications

```typescript theme={null}
session.events.onPhoneNotifications((notifications) => {
  notifications.forEach(notification => {
    console.log(`${notification.app}: ${notification.title}`);
    console.log(`Content: ${notification.content}`);
  });
});
```

### Connection Events

```typescript theme={null}
// When connection is lost
session.events.onDisconnected(() => {
  console.log('Connection lost');
});

// When connection is restored
session.events.onReconnected(() => {
  console.log('Connection restored');
});

// When session starts
session.events.onConnected((settings) => {
  console.log('Connected with settings:', settings);
});

// When errors occur
session.events.onError((error) => {
  console.error('Session error:', error);
});
```

## Event Patterns

### Debouncing Events

```typescript theme={null}
let timeout: NodeJS.Timeout;

session.events.onTranscription((data) => {
  clearTimeout(timeout);
  
  // Wait for user to stop speaking
  timeout = setTimeout(() => {
    processCompleteUtterance(data.text);
  }, 1000);
});
```

### State Machines

```typescript theme={null}
enum State {
  IDLE,
  LISTENING,
  PROCESSING
}

let currentState = State.IDLE;

session.events.onButtonPress((data) => {
  switch (currentState) {
    case State.IDLE:
      currentState = State.LISTENING;
      session.layouts.showTextWall('Listening...');
      break;
      
    case State.LISTENING:
      currentState = State.PROCESSING;
      session.layouts.showTextWall('Processing...');
      processInput();
      break;
  }
});
```

### Event Filtering

```typescript theme={null}
// Only respond to specific phrases
session.events.onTranscription((data) => {
  if (!data.isFinal) return; // Skip interim results
  
  const keywords = ['weather', 'time', 'news'];
  const hasKeyword = keywords.some(word => 
    data.text.toLowerCase().includes(word)
  );
  
  if (hasKeyword) {
    handleCommand(data.text);
  }
});
```

## Multi-User Events

For apps that support multiple users:

```typescript theme={null}
// Listen for messages from other users
session.events.onAppMessage((message) => {
  console.log(`From ${message.senderUserId}: ${message.payload}`);
});

// User joined
session.events.onAppUserJoined((userId) => {
  console.log(`${userId} joined`);
});

// User left
session.events.onAppUserLeft((userId) => {
  console.log(`${userId} left`);
});
```

## Best Practices

<AccordionGroup>
  <Accordion title="Clean up event handlers">
    Event handlers are automatically cleaned up when the session ends, but you can manually remove them:

    ```typescript theme={null}
    const cleanup = session.events.onTranscription(handler);
    // Later...
    cleanup(); // Remove this handler
    ```
  </Accordion>

  <Accordion title="Handle errors gracefully">
    ```typescript theme={null}
    session.events.onError((error) => {
      console.error('Session error:', error);
      // Show user-friendly message
      session.layouts.showTextWall('Something went wrong. Please try again.');
    });
    ```
  </Accordion>

  <Accordion title="Combine multiple events">
    ```typescript theme={null}
    let lastTranscript = '';
    let lastButtonPress = Date.now();

    session.events.onTranscription((data) => {
      lastTranscript = data.text;
    });

    session.events.onButtonPress((data) => {
      const timeSinceLastPress = Date.now() - lastButtonPress;
      if (timeSinceLastPress < 500) {
        // Double press detected
        processCommand(lastTranscript);
      }
      lastButtonPress = Date.now();
    });
    ```
  </Accordion>
</AccordionGroup>

## Performance Tips

* **Filter events early**: Return early from handlers if the event isn't relevant
* **Debounce rapid events**: Use timeouts to batch rapid events
* **Avoid blocking operations**: Use async/await for long-running tasks
* **Clean up resources**: Remove handlers and clear timers when done
