File: C:/Users/fred/.codex/.tmp/plugins/plugins/zoom/skills/zoom-apps-sdk/concepts/running-contexts.md
# Running Contexts
## Overview
A Zoom App can run in multiple surfaces within the Zoom client. The `runningContext` property returned by `config()` tells you where your app is currently loaded.
```javascript
const configResponse = await zoomSdk.config({
capabilities: ['getMeetingContext', 'getUserContext', ...],
version: '0.16'
});
console.log(configResponse.runningContext);
// 'inMeeting' | 'inMainClient' | 'inWebinar' | 'inImmersive' | ...
```
## All Running Contexts
| Context | Surface | Meeting APIs | User APIs | Layers APIs | Notes |
|---------|---------|-------------|-----------|-------------|-------|
| `inMeeting` | Meeting sidebar | Yes | Yes | Yes | Most common context |
| `inMainClient` | Main client panel | No | Yes | No | Home tab, no meeting running |
| `inWebinar` | Webinar sidebar | Yes | Yes | Yes | Host/panelist initially |
| `inImmersive` | Layers full-screen | Limited | Yes | Yes | After runRenderingContext |
| `inCamera` | Camera mode | Limited | Yes | Camera only | Virtual camera overlay |
| `inCollaborate` | Collaborate mode | Yes | Yes | No | Shared state context |
| `inPhone` | Zoom Phone | No | Yes | No | Phone call app surface |
| `inChat` | Team Chat | No | Yes | No | Chat sidebar |
## Context-Specific Behavior
### inMeeting (Most Common)
The primary context. Your app appears as a sidebar panel during a meeting.
```javascript
if (configResponse.runningContext === 'inMeeting') {
const meeting = await zoomSdk.getMeetingContext();
console.log('Meeting ID:', meeting.meetingID);
console.log('Topic:', meeting.meetingTopic);
const user = await zoomSdk.getUserContext();
console.log('Name:', user.screenName);
console.log('Role:', user.role); // 'host' | 'coHost' | 'attendee'
}
```
Available: All meeting APIs, sharing, invitations, breakout rooms, recording.
### inMainClient
Your app runs in the main Zoom window (not during a meeting). Used for dashboards, settings, pre-meeting setup.
```javascript
if (configResponse.runningContext === 'inMainClient') {
// NO meeting APIs available - getMeetingContext() will fail
const user = await zoomSdk.getUserContext();
console.log('Name:', user.screenName);
// Can still use connect() to sync with meeting instance later
}
```
**Key limitation:** No meeting context, no participants, no sharing.
### inWebinar
Similar to inMeeting but for webinars. Initially only available to host and panelists.
```javascript
if (configResponse.runningContext === 'inWebinar') {
const user = await zoomSdk.getUserContext();
// role: 'host' | 'panelist' | 'attendee'
if (user.role === 'attendee') {
// Limited functionality for attendees
}
}
```
### inImmersive / inCamera
Layers API contexts. Your app has taken over the video rendering.
- `inImmersive`: Full-screen custom layout (replaces gallery view)
- `inCamera`: Overlay on user's camera feed
See [Layers API Reference](../references/layers-api.md) for details.
## Multiple Instances
A Zoom App can have **two instances running simultaneously**:
1. **Main client instance** (`inMainClient`) - Always available
2. **Meeting instance** (`inMeeting`) - Created when user opens app in meeting
### Instance Communication
Use `connect()` and `postMessage()` to sync between instances:
```javascript
// Both instances call connect()
await zoomSdk.connect();
// Listen for connection
zoomSdk.addEventListener('onConnect', (event) => {
console.log('Connected to other instance');
});
// Send data to other instance
await zoomSdk.postMessage({ type: 'settings', data: mySettings });
// Receive data from other instance
zoomSdk.addEventListener('onMessage', (event) => {
const { type, data } = JSON.parse(event.payload);
if (type === 'settings') {
applySettings(data);
}
});
```
**Pattern: Pre-Meeting Setup**
```
Main Client Instance Meeting Instance
───────────────────── ─────────────────
User configures settings --> connect() + listen
Store in state --> onConnect fires
postMessage('getSettings')
onMessage('getSettings') -->
postMessage(settings) --> onMessage(settings)
Apply settings to meeting
```
## Detecting Context at Runtime
```javascript
import zoomSdk from '@zoom/appssdk';
async function init() {
const config = await zoomSdk.config({
capabilities: [
'getMeetingContext', 'getUserContext', 'getRunningContext',
'connect', 'postMessage', 'onConnect', 'onMessage',
'shareApp', 'runRenderingContext'
],
version: '0.16'
});
switch (config.runningContext) {
case 'inMeeting':
case 'inWebinar':
initMeetingUI();
break;
case 'inMainClient':
initDashboardUI();
break;
case 'inImmersive':
case 'inCamera':
initLayersUI();
break;
default:
initFallbackUI();
}
}
```
## Checking API Availability
Not all APIs are available in all contexts. Use `getSupportedJsApis()` to check:
```javascript
const { supportedApis } = await zoomSdk.getSupportedJsApis();
if (supportedApis.includes('authorize')) {
// In-Client OAuth is available
showAuthButton();
}
if (supportedApis.includes('runRenderingContext')) {
// Layers API is available
showLayersButton();
}
```
Also check `configResponse.unsupportedApis` after `config()` for capabilities that were requested but not available in the current client version.
## Resources
- **Running contexts docs**: https://developers.zoom.us/docs/zoom-apps/guides/in-client-experience/
- **Instance communication**: https://developers.zoom.us/docs/zoom-apps/guides/collaborate-mode/