Overview
The Overlays module provides a custom streaming overlay editor where users can create, configure, and manage overlays with layered widgets. Each overlay has a unique key used for popout access in OBS browser sources. Overlays support configurable dimensions, background settings, and multiple layer types (alerts, chat, music, custom HTML/CSS). Layers are ordered by sort_order and can be individually toggled visible/hidden.
Architecture
Backend
- GraphQL (
apps/api/src/graphql/overlays.rs) -- Full CRUD for overlays and layers. Queries for listing/fetching overlays and their layers. Mutations for create, update, delete overlays and bulk-replace layers.
- Database (
apps/api/src/db/overlays.rs) -- PostgreSQL operations for overlays and overlay_layers tables. Includes generate_overlay_key() which creates a 12-character URL-safe random key.
- Popout Access -- Overlays are accessed via
/overlay/[key]?token=xxx using popout tokens for non-expiring OBS browser source access.
Frontend
- Overlay editor UI in the Next.js web app.
- Popout overlay renderer loads via the unique overlay key.
- Layer configuration per layer type (alert config, chat style, music widget config, custom HTML/CSS/JS).
API
GraphQL Queries
| Query | Permission | Description |
|---|
overlays | overlays:read | List all overlays for the account |
overlay(id: UUID) | overlays:read | Get a single overlay by ID |
overlayLayers(overlayId: UUID) | overlays:read | Get all layers for an overlay, ordered by sort_order |
GraphQL Mutations
| Mutation | Permission | Description |
|---|
createOverlay(input: CreateOverlayInput) | overlays:create | Create a new overlay (defaults: 1920x1080, "transparent" background, "Main Overlay" name) |
updateOverlay(input: UpdateOverlayInput) | overlays:edit | Update overlay name, dimensions, or background |
updateOverlayLayers(overlayId: UUID, layers: JSON) | overlays:edit | Bulk-replace all layers for an overlay. Each layer has: type, name, config (JSONB), visible, sort_order. Optionally include id to preserve identity. |
deleteOverlay(id: UUID) | overlays:delete | Delete an overlay and all its layers |
REST Endpoints
All paths live under /v1/overlays. Bodies are snake_case and mirror the GraphQL inputs.
| Method | Path | Permission | Description |
|---|
GET | /v1/overlays | overlays:read | List overlays for the account |
POST | /v1/overlays | overlays:create | Create an overlay |
GET | /v1/overlays/{id} | overlays:read | Get an overlay with its layers |
PATCH | /v1/overlays/{id} | overlays:edit | Update name, dimensions, background, or layers |
DELETE | /v1/overlays/{id} | overlays:delete | Delete an overlay and its layers |
CreateOverlayInput:
| Field | Type | Default | Description |
|---|
name | String? | "Main Overlay" | Overlay name |
width | i32? | 1920 | Canvas width in pixels |
height | i32? | 1080 | Canvas height in pixels |
background | String? | "transparent" | Background color/value |
UpdateOverlayInput:
| Field | Type | Description |
|---|
id | UUID | Overlay ID (required) |
name | String? | New name |
width | i32? | New width |
height | i32? | New height |
background | String? | New background |
Permissions
| Permission | Description |
|---|
overlays:read | View overlay configuration and layers |
overlays:create | Create new overlays |
overlays:edit | Edit overlay settings and layers |
overlays:delete | Delete overlays |
Database
| Table | Database | Description |
|---|
overlays | PostgreSQL | id, account_id, name, key (unique 12-char URL-safe string), width, height, background, created_at, updated_at |
overlay_layers | PostgreSQL | id, overlay_id (FK), type (layer type string), name, config (JSONB), visible (bool), sort_order (int), created_at, updated_at |
Overlay Key Generation
The generate_overlay_key() function creates a 12-character random string using characters A-Z, a-z, 0-9, -, _. This key is used in the popout URL: /overlay/[key]?token=xxx.
Data Flow
- User creates an overlay via the editor. A unique key is generated.
- User adds layers (alert, chat, music, custom) and configures each one.
- Layers are saved via
updateOverlayLayers mutation (bulk replace).
- The overlay is accessed in OBS via its popout URL with a popout token.
- The popout page loads the overlay and all its layers, connecting to WebSocket for real-time updates.
Key Files
| Path | Description |
|---|
apps/api/src/graphql/overlays.rs | GraphQL queries and mutations |
apps/api/src/db/overlays.rs | Database operations and key generation |