Appearance
Environment Config
Each environment can be fine-tuned with feature flags that apply to all users and SDK clients connecting to it.
What It Is
Environment config is a set of tenant-controlled toggles and limits stored per environment. When a client connects via WebSocket and authenticates, the server sends the current config in the auth:ok response. The widget reads these flags to show or hide features, and the server enforces them on uploads.
When Do Changes Take Effect?
Config is loaded once per WebSocket connection during authentication. Connected clients must reconnect (e.g., refresh the page) to pick up changes.
All Settings
Media
| Setting | Type | Default | Description |
|---|---|---|---|
allowImages | boolean | true | Allow image file attachments |
allowAudio | boolean | true | Allow audio recording attachments |
allowVideo | boolean | true | Allow video recording attachments |
maxFileSizeMb | number | 10 | Maximum file size per attachment (MB) |
maxAttachmentsPerComment | number | 5 | Maximum attachments per comment |
Features
| Setting | Type | Default | Description |
|---|---|---|---|
allowReactions | boolean | true | Enable emoji reactions on comments |
allowDrawing | boolean | true | Enable freehand drawing overlay |
allowMentions | boolean | true | Enable @mention autocomplete in comments |
Display
| Setting | Type | Default | Description |
|---|---|---|---|
showCursors | boolean | true | Show live cursor positions |
showPresence | boolean | true | Show presence avatars in the toolbar |
showTypingIndicators | boolean | true | Show "is typing..." indicators in threads |
P2P / Real-Time Data
| Setting | Type | Default | Description |
|---|---|---|---|
allowP2P | boolean | false | Enable P2P data channels (WebRTC + CRDT) |
p2pMeshLimit | number | 6 | Max peers for direct P2P mesh; beyond this, WebSocket fallback |
p2pPersistIntervalMs | number | 5000 | How often CRDT state auto-saves to server (ms) |
p2pStateTTLDays | number | 30 | Days of inactivity before persisted P2P state is cleaned up |
p2pMaxStateBytes | number | 5242880 | Max CRDT state size per room (bytes, default 5 MB) |
maxSharedObjects | number | 20 | Max shared data structures (maps, lists, counters) per room |
allowP2PBinary | boolean | false | Allow binary data on raw P2P channels |
TURN Server
| Setting | Type | Default | Description |
|---|---|---|---|
turnServerUrl | string | null | null | TURN server URL (e.g., turn:turn.example.com:3478) |
turnSecret | string | null | null | Shared secret for time-limited TURN credentials |
TURN Setup
A TURN server is needed when users are behind strict firewalls or symmetric NATs. See the P2P overview for details. When configured, the SDK auto-fetches credentials — your frontend code doesn't change.
Configuring via the Admin Panel
- Log in to the Admin Panel and navigate to Environments
- Click on the environment you want to configure
- Click the Configure Environment button on the detail page
- A modal opens with toggles (booleans) and number inputs (limits)
- Save — the new config is persisted immediately
How It's Enforced
Enforcement happens at two layers:
Server (uploads): When a file is uploaded via POST /api/v1/upload, the server checks allowImages, allowAudio, allowVideo, and maxFileSizeMb. Disabled types return 403, oversized files return 413.
Widget (UI): On connect, the widget reads the config and:
- Hides the image/audio/video buttons if the corresponding type is disabled
- Hides the drawing pen icon if
allowDrawingis false - Hides presence avatars if
showPresenceis false - Suppresses typing indicators if
showTypingIndicatorsis false
Accessing Config in Code
If you're using the Client SDK directly, the current config is available after authentication:
typescript
client.state.on('auth', () => {
const config = client.state.config;
if (!config.allowDrawing) {
// hide your custom draw button
}
console.log(`Max file size: ${config.maxFileSizeMb}MB`);
});The config property is read-only and reflects what the server sent on the last successful auth.
typescript
interface EnvironmentConfig {
// Media
allowImages: boolean;
allowAudio: boolean;
allowVideo: boolean;
maxFileSizeMb: number;
maxAttachmentsPerComment: number;
// Features
allowReactions: boolean;
allowDrawing: boolean;
allowMentions: boolean;
// Display
showCursors: boolean;
showPresence: boolean;
showTypingIndicators: boolean;
// P2P
allowP2P: boolean;
p2pMeshLimit: number;
p2pPersistIntervalMs: number;
p2pStateTTLDays: number;
p2pMaxStateBytes: number;
maxSharedObjects: number;
allowP2PBinary: boolean;
turnServerUrl: string | null;
turnSecret: string | null;
}