Skip to main content
The dashboard provides persistent UI that appears when users look up. Use it for status updates and notifications that don’t require full attention.

Basic Usage

session.dashboard.content.writeToMain('New message received');
With title and content:
session.dashboard.content.writeToMain('App Status\nConnected and running');

Dashboard Modes

Main Mode (Default)

session.dashboard.content.writeToMain('Status: Active');

Expanded Mode

More detailed information:
session.dashboard.content.writeToExpanded('Detailed status information here');

Clearing Dashboard

session.dashboard.content.writeToMain('');

Best Practices

Use for background info:
// ✅ Good - status updates
session.dashboard.content.writeToMain('3 unread messages');

// ❌ Avoid - main app content
session.dashboard.content.writeToMain('Welcome! Here is a long message...');
// ^ Use layouts for this instead
Keep updates brief:
// ✅ Good
session.dashboard.content.writeToMain('Recording: 1:23');

// ❌ Avoid
session.dashboard.content.writeToMain(
  'You have been recording for 1 minute and 23 seconds'
);
Updates are auto-throttled: MentraOS automatically throttles display updates to 1 every 300ms to prevent display desync:
// You can update frequently - cloud handles throttling
session.events.onTranscription((data) => {
  if (data.isFinal) {
    session.dashboard.content.writeToMain(`Message: ${data.text}`);
  }
});

Common Patterns

Status Updates

session.events.onTranscription(async (data) => {
  if (data.isFinal) {
    // Show user input
    session.layouts.showTextWall(data.text);
    
    // Update dashboard with status
    session.dashboard.content.writeToMain('Processing...');
    
    // Process and show result
    const response = await processInput(data.text);
    session.layouts.showTextWall(response);
    
    // Clear dashboard
    session.dashboard.content.writeToMain('');
  }
});

Real-Time Counters

let messageCount = 0;

session.events.onTranscription((data) => {
  if (data.isFinal) {
    messageCount++;
    
    // Update main display
    session.layouts.showTextWall(data.text);
    
    // Show count in dashboard
    session.dashboard.content.writeToMain(`Messages: ${messageCount}`);
  }
});

Recording Status

let recordingStartTime: number;
let recordingInterval: NodeJS.Timeout;

function startRecording(session: AppSession) {
  recordingStartTime = Date.now();
  
  recordingInterval = setInterval(() => {
    const elapsed = Math.floor((Date.now() - recordingStartTime) / 1000);
    const minutes = Math.floor(elapsed / 60);
    const seconds = elapsed % 60;
    
    session.dashboard.content.writeToMain(
      `Recording: ${minutes}:${seconds.toString().padStart(2, '0')}`
    );
  }, 1000);
}

function stopRecording(session: AppSession) {
  clearInterval(recordingInterval);
  session.dashboard.content.writeToMain('');
}

Notification Counts

let notificationCount = 0;

session.events.onPhoneNotification((data) => {
  if (['Messages', 'Email'].includes(data.app)) {
    notificationCount++;
    session.dashboard.content.writeToMain(`${notificationCount} notifications`);
  }
});

Dashboard API

MethodDescription
content.writeToMain(text)Update main dashboard
content.writeToExpanded(text)Update expanded dashboard
content.write(text, modes)Update specific modes
content.onModeChange(callback)Listen for mode changes
Dashboard updates are automatically throttled to 1 per 300ms by MentraOS Cloud to prevent display desync.

When to Use Dashboard vs Layouts

Use CaseUse DashboardUse Layouts
Main app content
Status updates
Notifications
User input/output
Persistent info
Detailed content

Next Steps