@lumiastream/lumia-types 3.2.6 → 3.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,54 +2,47 @@
2
2
 
3
3
  ---
4
4
 
5
- ## 0. Plugin Handoff Rules
5
+ ## 0. Overlay-First Rule
6
6
 
7
- Use overlays for presentation. Hand off to a plugin when the request needs:
7
+ Build normal user requests as Custom Overlays. Chat overlays, alert popups, counters, goals, scoreboards, games, animations, API fetches, polling, command calls, chatbot messages, storage, and variable workflows belong in overlay HTML/CSS/JS/Configs/Data.
8
8
 
9
- - integration logic reused across overlays/commands/automations
10
- - manifest-driven Lumia setup (settings/actions/variables/alerts)
11
- - custom alert triggering/variation workflows
12
- - runtime behavior that should not depend on a specific overlay session
13
- - installable/distributable plugin packaging (`.lumiaplugin`)
14
- - Node.js runtime execution and Node-only library/dependency usage
15
-
16
- Plugin + overlay bridge contract:
17
-
18
- - Plugin writes global variables (`this.lumia.setVariable`).
19
- - Plugin triggers alerts (`this.lumia.triggerAlert`) with payload in `extraSettings`.
20
- - Overlay reads variables (`Overlay.getVariable('key')`) and alert payload from `data.extraSettings`.
21
- - Use `dynamic` only for alert variation matching.
22
-
23
- If plugin work is needed, point users to:
24
-
25
- - Plugin SDK docs: https://dev.lumiastream.com/docs/plugin-sdk/overview
26
- - Plugin GPT: https://chatgpt.com/g/g-6908e861c7f88191819187b9f5fbcfd7-lumia-plugin-gpt
9
+ Only hand off when the user explicitly needs code that runs outside an overlay session, packaging/distribution, Node-only dependencies, or reusable integration logic across multiple Lumia features.
27
10
 
28
11
  ---
29
12
 
30
13
  ## 1. API Cheat‑Sheet (one line per member)
31
14
 
15
+ Runtime reminders:
16
+
17
+ - `Overlay.on(...)` handlers receive raw payload data, not a `CustomEvent`.
18
+ - Read Config/Data values from `Overlay.data`, not from a bare top-level `data` variable.
19
+ - JS is already wrapped by Lumia in an async function, so top-level `await` is allowed.
20
+ - Use literal listener names like `Overlay.on('chat', ...)` so Lumia can auto-subscribe to events.
21
+ - Use `Overlay.deleteStorage`, not `Overlay.removeStorage`.
22
+
32
23
  ### `window.Overlay` interface
33
24
 
34
25
  | Signature | Purpose | |
35
26
  | ----------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | --- |
36
- | `on(event: 'chat'\|'alert'\|'hfx'\|'virtuallight'\|'overlaycontent', handler: (ev: CustomEvent<OverlayEvent>) => void)` | Subscribe to realtime overlay events. | |
37
- | `callCommand(command: string, extraSettings?: Record<string,string \| number>): void` | Trigger a Lumia Stream command, optionally passing local variables. | |
27
+ | `on(event: 'chat'\|'alert'\|'hfx'\|'virtuallight'\|'overlaycontent', handler: (data: OverlayEvent) => void)` | Subscribe to real-time overlay events. Handler receives raw data. | |
28
+ | `callCommand(command: string, extraSettings?: Record<string, unknown>): Promise<unknown>` | Trigger a Lumia Stream command, optionally passing local variables. | |
38
29
  | `chatbot({ message, platform?, chatAsSelf? }): Promise<void>` | Send a chat message as the bot or streamer on the chosen platform(s). | |
39
30
  | `addLoyaltyPoints({ value, username, platform }): Promise<number>` | Add or subtract loyalty points for a user and get the new balance. | |
40
31
  | `getLoyaltyPoints({ username, platform }): Promise<number>` | Retrieve a user's current loyalty‑points total. | |
41
- | `setVariable(name: string, value: unknown): void` | Create or update a global Lumia variable. | |
42
- | `getVariable(name: string): unknown` | Read a global Lumia variable (**must be a string literal key**). | |
43
- | `saveStorage(key: string, value: string): void` | Persist data scoped to this overlays `codeId`. | |
44
- | `getStorage(key: string): string` | Load a value previously saved with `saveStorage`. | |
45
- | `removeStorage(key: string): void` | Delete a saved storage item. | |
32
+ | `setVariable(name: string, value: unknown): Promise<unknown>` | Create or update a global Lumia variable. | |
33
+ | `getVariable(name: string): Promise<unknown>` | Read a global Lumia variable (**must be a string literal key**). | |
34
+ | `saveStorage(key: string, value: unknown): Promise<unknown>` | Persist data scoped to this overlay's `codeId`. | |
35
+ | `getStorage(key: string): Promise<unknown>` | Load a value previously saved with `saveStorage`. | |
36
+ | `deleteStorage(key: string): Promise<unknown>` | Delete a saved storage item. | |
46
37
 
47
38
  **Global helpers**
48
39
 
49
- `toast(message: string, type?: 'info'\|'success'\|'warning'\|'error')` • `log(...args)` (alias of `console.log`)
40
+ `toast(message: string, type?: 'info'\|'success'\|'warning'\|'error')` • `console.log(...args)` `console.error(...args)`
50
41
 
51
42
  ### Overlay events & payload helpers
52
43
 
44
+ Reference only. Overlay JS output should still be plain JavaScript, not TypeScript.
45
+
53
46
  ```js
54
47
  type OverlayListener = 'chat' | 'alert' | 'hfx' | 'virtuallight' | 'overlaycontent';
55
48
  interface ChatEvent {
@@ -180,8 +173,8 @@ Include these two helper aliases in your embeddings so the model can quickly map
180
173
  ### Positive – Chat listener
181
174
 
182
175
  ```js
183
- Overlay.on('chat', (ev) => {
184
- const { username, message } = ev.detail;
176
+ Overlay.on('chat', (data) => {
177
+ const { username, message } = data;
185
178
  toast(`${username}: ${message}`);
186
179
  });
187
180
  ```
@@ -18,52 +18,11 @@ Access it here: [Chat GPT Lumia Overlay Assistant](https://chatgpt.com/g/g-6760d
18
18
 
19
19
  ---
20
20
 
21
- ## 🔌 Plugin + Overlay Integration
21
+ ## Overlay Scope
22
22
 
23
- Use overlays for visual rendering and interaction. Overlays can also call APIs and run polling logic directly.
24
- Use plugins when plugin capabilities clearly outshine overlay-only solutions, such as reusable cross-feature integrations, manifest-driven settings/actions/alerts, custom alert triggering with variations, runtime logic that should not depend on a specific overlay session, or Node.js runtime/library requirements.
23
+ Custom Overlays should handle visual rendering, chat and alert listeners, HFX and virtual light reactions, browser API calls, polling, commands, chatbot messages, storage, variables, games, and animations directly in the five overlay tabs.
25
24
 
26
- When building both together, use this contract:
27
-
28
- 1. Plugin writes global variables with `this.lumia.setVariable("key", value)`.
29
- 2. Plugin triggers alerts with `this.lumia.triggerAlert(...)`.
30
- 3. Overlay reads:
31
- - global variables via `Overlay.getVariable("key")` or `{{key}}`
32
- - alert payload via `Overlay.on("alert", (data) => data.extraSettings)`
33
-
34
- `triggerAlert` payload guidance:
35
-
36
- - `dynamic` is only for variation matching.
37
- - `extraSettings` can contain any key/value payload and is the recommended data bridge for overlays/templates.
38
- - If an alert does not use variation conditions, omit `dynamic` and send only `extraSettings`.
39
-
40
- Example plugin payload:
41
-
42
- ```js
43
- await this.lumia.triggerAlert({
44
- alert: 'rumble_stream_started',
45
- extraSettings: {
46
- username: state.username,
47
- stream_title: state.title,
48
- viewer_count: state.viewerCount,
49
- },
50
- });
51
- ```
52
-
53
- Example overlay listener:
54
-
55
- ```js
56
- Overlay.on('alert', (data) => {
57
- if (data.alert !== 'rumble_stream_started') return;
58
- const payload = data.extraSettings || {};
59
- document.getElementById('title').textContent = payload.stream_title || 'Untitled';
60
- });
61
- ```
62
-
63
- For plugin implementation details:
64
-
65
- - Plugin SDK docs: [Plugin SDK Overview](https://dev.lumiastream.com/docs/plugin-sdk/overview)
66
- - Plugin GPT: [Lumia Plugin GPT](https://chatgpt.com/g/g-6908e861c7f88191819187b9f5fbcfd7-lumia-plugin-gpt)
25
+ Use another Lumia workflow only when the user explicitly needs code that runs outside an overlay session, packaging/distribution, Node-only dependencies, or reusable integration logic across multiple Lumia features.
67
26
 
68
27
  ---
69
28
 
@@ -91,7 +50,7 @@ Customize the visual style of your overlay:
91
50
  #msg {
92
51
  font-weight: bold;
93
52
  /* You can use variables directly within CSS */
94
- color: '{{mycolor}}';
53
+ color: {{mycolor}};
95
54
  }
96
55
  ```
97
56
 
@@ -102,61 +61,57 @@ Customize the visual style of your overlay:
102
61
  Javascript handles initialization and real-time event updates for your overlay:
103
62
 
104
63
  ```js
105
- // window.Overlay is our primary api, you can use it with window.Overlay or just Overlay
64
+ // window.Overlay is the primary API. You can use it as window.Overlay or Overlay.
106
65
 
107
- // Overlay.data contains he data that's submitted from the user using your overlay that they're allowed to fill out based on the fields in the config tab
66
+ // Overlay.data contains the current Data tab values.
108
67
  console.log(Overlay.data);
109
68
 
110
- // Call a command in Lumia Stream and pass variables for the command to use. In the command you can reference {{secret}} since that's what we're passing in
111
- Overlay.callCommand('mycommand', { secret: 'password' });
69
+ // Call a command in Lumia Stream and pass local variables for that command run.
70
+ // In the command, you can reference {{secret}} because it is passed here.
71
+ await Overlay.callCommand("mycommand", { secret: "password" });
112
72
 
113
- // Send a chatbot message to the corresponding platform either as the streamer or the bot. Leave the platform as null to trigger on all connected platforms
114
- Overlay.chatbot({ message: 'This works', platform: 'twitch', chatAsSelf: false });
73
+ // Send a chatbot message to one platform, or omit platform for all connected platforms.
74
+ await Overlay.chatbot({ message: "This works", platform: "twitch", chatAsSelf: false });
115
75
 
116
- // Add Loyalty Points for a user, also returns the new updated points value
117
- const points = await Overlay.addLoyaltyPoints({ value: 100, username: 'lumiastream', platform: 'twitch' });
118
- // Or if you don't care about the response
119
- Overlay.addLoyaltyPoints({ value: 100, username: 'lumiastream', platform: 'twitch' });
120
- // You can also subtract points
121
- Overlay.addLoyaltyPoints({ value: -100, username: 'lumiastream', platform: 'twitch' })
76
+ // Add or subtract loyalty points for a user.
77
+ const points = await Overlay.addLoyaltyPoints({ value: 100, username: "lumiastream", platform: "twitch" });
78
+ await Overlay.addLoyaltyPoints({ value: -100, username: "lumiastream", platform: "twitch" });
122
79
 
123
- // Gets the amount of loyalty points that a user has
124
- const usersPoints = await Overlay.getLoyaltyPoints({ username: 'lumiastream', platform: 'twitch' });
80
+ // Get the amount of loyalty points that a user has.
81
+ const usersPoints = await Overlay.getLoyaltyPoints({ username: "lumiastream", platform: "twitch" });
125
82
 
126
- // If the variables isn't already created it will create one.
127
- await Overlay.setVariable('myvar', 'this works');
83
+ // Create or update a global Lumia variable.
84
+ await Overlay.setVariable("myvar", "this works");
128
85
 
129
- // Retrieves a variable, always use a string for getVariable, do not use a reference to a string so that the code can extract out the variables it needs to listen to
130
- await Overlay.getVariable('myvar');
86
+ // Retrieve a variable. Always use a string literal key.
87
+ const variable = await Overlay.getVariable("myvar");
131
88
 
132
- // If the variable was not previously created it may not automatically be replaced in your code until after the code is saved and reopened. If the overlay was previously made then it will update immediately. It may be helpful to add a check in your code to see if variable is already auto updating or not and toast the user to refresh the overlay
89
+ // If the variable was just created, variable replacement may require saving and refreshing once.
133
90
  const usedMyVar = "{{myvar}}";
134
91
 
135
- // You can call await without an async function since an async function is already wrapped around all the JS code
92
+ // You can use await at the top level because Lumia wraps the JS tab in an async function.
136
93
 
137
94
  // Save an item to storage
138
- await Overlay.saveStorage('mydata', 151);
95
+ await Overlay.saveStorage("mydata", 151);
139
96
 
140
- // Get an item from stoage
141
- const pokemonCaught = await Overlay.getStorage('mydata');
97
+ // Get an item from storage
98
+ const pokemonCaught = await Overlay.getStorage("mydata");
142
99
 
143
- // Delete an item from stoage
144
- await Overlay.deleteStorage('mydata');
100
+ // Delete an item from storage
101
+ await Overlay.deleteStorage("mydata");
145
102
 
146
- Overlay.on('chat', (data) => {
103
+ Overlay.on("chat", (data) => {
147
104
  const username = data.username;
148
- const avatar = data.avatar;
149
105
  const message = data.message;
150
106
  toast(`New chat message received from ${username}. They said ${message}`);
151
107
  });
152
- Overlay.on('alert', (data) => {
153
- console.log('alert', data);
154
- const settings = data.extraSettings;
155
- const username = settings?.username || 'unknown';
156
- const amount = data.dynamic.value;
157
- const avatar = settings?.avatar;
158
108
 
159
- if (data.alert === 'twitch-subscriber') {
109
+ Overlay.on("alert", (data) => {
110
+ console.log("alert", data);
111
+ const settings = data.extraSettings || {};
112
+ const username = settings.username || "unknown";
113
+
114
+ if (data.alert === "twitch-subscriber") {
160
115
  if (data.dynamic.isGift) {
161
116
  console.log(`${username} sent ${data.dynamic.giftAmount} with a tier ${settings.subPlan} sub to ${settings.recipients ?? settings.recipient}`);
162
117
  } else if (data.dynamic.isResub) {
@@ -166,38 +121,39 @@ Overlay.on('alert', (data) => {
166
121
  }
167
122
  }
168
123
 
169
- if (data.alert === 'twitch-raid') {
124
+ if (data.alert === "twitch-raid") {
170
125
  console.log(`${username} just raided with ${data.dynamic.value} viewers`);
171
126
  }
172
127
 
173
- if (data.alert === 'kick-follower') {
128
+ if (data.alert === "kick-follower") {
174
129
  console.log(`${username} just followed on Kick`);
175
130
  }
176
131
  });
177
- Overlay.on('hfx', (data) => {
132
+
133
+ Overlay.on("hfx", (data) => {
178
134
  const username = data.username;
179
135
  const command = data.command;
180
136
  const message = data.message; // If the HFX was triggered with a message
181
- const avatar = data.avatar;
182
137
 
183
138
  console.log(`${username} just triggered HFX ${command}`);
184
139
  });
185
- Overlay.on('virtuallight', (data) => {
186
- console.log('virtuallight', data);
187
- const viratlLightId = data.uuid;
140
+
141
+ Overlay.on("virtuallight", (data) => {
142
+ console.log("virtuallight", data);
143
+ const virtualLightId = data.uuid;
188
144
  const brightness = data.brightness;
189
145
 
190
- // Power sometimes does not come through if the light is just changing colors
191
- if (data.color && (data.power || data.power === 'undefined')) {
192
- const { r, g, b} = data.color;
193
- console.log(`Light is changing to the color to rgb(${r},${g},${b})`);
146
+ if (data.color) {
147
+ const { r, g, b } = data.color;
148
+ console.log(`Light ${virtualLightId} changed to rgb(${r}, ${g}, ${b}) at ${brightness}%`);
194
149
  } else if (data.power === false) {
195
- console.log(`Light is turning off`);
150
+ console.log(`Light ${virtualLightId} is turning off`);
196
151
  }
197
- const
198
152
  });
199
- // Only codeId that matches on both Overlays and Lumia will trigger this listener. codeId can only contain letters, numbers, hyphens, and underscores. Max 25 characters.
200
- Overlay.on('overlaycontent', (data) => {
153
+
154
+ // Only matching codeId values trigger this listener.
155
+ // codeId can only contain letters, numbers, hyphens, and underscores. Max 25 characters.
156
+ Overlay.on("overlaycontent", (data) => {
201
157
  const content = data.content;
202
158
  console.log(`Content has been sent from Lumia Stream ${content}`);
203
159
  });
@@ -241,7 +197,7 @@ Overlay.on('overlaycontent', (data) => {
241
197
  });
242
198
  ```
243
199
 
244
- When using Overlay.on the data tab must have the corresponding OverlayListener types:
200
+ Lumia auto-detects event subscriptions from literal `Overlay.on("event", ...)` calls in the JS tab. Use direct string literals so the overlay subscribes to the needed events. The Data tab only needs an `events` array for legacy/manual cases.
245
201
 
246
202
  ### OverlayListener types
247
203
 
@@ -253,9 +209,9 @@ When using Overlay.on the data tab must have the corresponding OverlayListener t
253
209
  | virtuallight | Virtual lights |
254
210
  | overlaycontent | Custom Overlay Content |
255
211
 
256
- > 💡 Performance Tip: Only the selected events will be delivered to the overlay.
257
- > 💡 The typescript types for each alert is within the types tab
258
- > 💡 `overlaycontent` is a default event that will always be on for all custom overlays that are automatically subscribed to whether it's in the data tab or not. This is a special event that allows you to send custom content to the overlay from Lumia Stream and will only send to your specific codeId.
212
+ > 💡 Performance Tip: Only selected events are delivered to the overlay.
213
+ > 💡 The TypeScript types for each alert are within the Types tab.
214
+ > 💡 `overlaycontent` sends custom content only to custom overlay layers with the matching `codeId`.
259
215
 
260
216
  ### Showing Toasts
261
217
 
@@ -306,7 +262,17 @@ Overlay.setVariable('pokemon_caught', 151);
306
262
 
307
263
  ### Using Persistent Storage in Lumia Stream
308
264
 
309
- We expose an api that allows you to get, update, and delete storage tied to your `codeId`. This will persist across Lumia Stream and can be used to communicate with your overlays in any place: OBS, Browser, Meld, etc. It works different than localStorage where localStorage only saves for the browser / streaming studio. If you would like to persist data this is the recommended way other than using it with variables. The only issue is that actual Lumia Stream does not have access to this storage currently. Only your Overlays will have access
265
+ We expose an api that allows you to get, update, and delete storage tied to your `codeId`. This persists across Lumia Stream and can be used to communicate with your overlays in any place: OBS, Browser, Meld, etc. If you want to persist data this is the recommended way, along with variables. Note that Lumia Stream commands and chatbots cannot read this storage currently only your Overlays can.
266
+
267
+ > **First-load note:** `Overlay.getStorage(key)` returns `null` when the key has never been saved, and Lumia will show a red error toast in that case. Always default the value and seed the key on first load:
268
+ >
269
+ > ```js
270
+ > let counter = await Overlay.getStorage('counter');
271
+ > if (counter == null) {
272
+ > counter = 0;
273
+ > await Overlay.saveStorage('counter', counter);
274
+ > }
275
+ > ```
310
276
 
311
277
  This can be used under `Overlay.saveStorage`, `Overlay.getStorage`, `Overlay.deleteStorage`
312
278
 
@@ -323,48 +289,46 @@ await Overlay.deleteStorage('pokemon_caught');
323
289
 
324
290
  ### Data Storage Options in Custom Overlays
325
291
 
326
- When building custom overlays, you have several options for storing and sharing data. Each method has its own use cases, benefits, and limitations:
327
-
328
- #### 1. `localStorage`
329
-
330
- - **Scope:** Only available in the browser where the overlay is loaded (e.g., OBS, browser source, or streaming studio).
331
- - **Persistence:** Data persists across page reloads in the same browser, but is not shared between different browsers or devices.
332
- - **Use Case:** Storing user preferences or temporary data that doesn't need to sync across devices or overlays.
333
- - **Limitations:** Not accessible by Lumia Stream itself or other overlays running elsewhere.
292
+ Use one of these three. Do not use browser `localStorage` or `sessionStorage` in overlays they are not shared across OBS/browser sources and are explicitly disallowed.
334
293
 
335
- #### 2. **Lumia Stream Variables**
294
+ #### 1. Lumia Stream Variables
336
295
 
337
- - **Scope:** Global within Lumia Stream. Variables can be accessed and updated by overlays, chatbots, commands, and other Lumia features.
296
+ - **Scope:** Global within Lumia Stream. Accessible by overlays, chatbots, commands, and other Lumia features.
338
297
  - **Persistence:** Saved on the server and available across all overlays and sessions.
339
- - **Use Case:** Sharing data between overlays, commands, and chatbots, or persisting state across restarts.
340
- - **Limitations:** All variables are global—be careful with naming to avoid conflicts.
298
+ - **Use Case:** Shared state that chatbots/commands/other overlays need to read or write.
299
+ - **Limitations:** Variables are global pick unique names.
300
+ - **API:** `Overlay.setVariable(name, value)` / `Overlay.getVariable(name)`.
301
+
302
+ #### 2. `Overlay.saveStorage` / `getStorage` / `deleteStorage`
303
+
304
+ - **Scope:** Persistent storage tied to your overlay's `codeId`. Shared across every overlay instance running on the same Lumia Stream server (OBS, browser, Meld, etc.).
305
+ - **Persistence:** Persists across overlay reloads and app restarts.
306
+ - **Use Case:** Overlay-specific state that other overlays with the same `codeId` need to see.
307
+ - **Limitations:** Overlays only — Lumia commands and chatbots cannot read it. Not synced across servers.
308
+ - **First-load note:** `getStorage` returns `null` when the key has never been saved and the host will display a red error toast. Always default the value and seed it on first load:
309
+
310
+ ```js
311
+ let counter = await Overlay.getStorage("counter");
312
+ if (counter == null) {
313
+ counter = 0;
314
+ await Overlay.saveStorage("counter", counter);
315
+ }
316
+ ```
341
317
 
342
318
  #### 3. `Overlay.callCommand`
343
319
 
344
- - **Scope:** Triggers a Lumia Stream command, optionally passing custom data.
345
- - **Persistence:** Depends on your command logic. You can implement your own storage or logic inside the command.
346
- - **Use Case:** Advanced workflows where you want to process data or trigger actions in Lumia Stream, possibly updating variables or storage as part of the command.
347
- - **Limitations:** Requires custom command setup in Lumia Stream.
348
-
349
- #### 4. `Overlay.saveStorage` / `getStorage` / `deleteStorage`
350
-
351
- - **Scope:** Persistent storage tied to your overlay's `codeId`. Data is saved on the local Lumia Stream server and is accessible from any overlay instance (e.g., OBS, browser, Meld) running on the same server.
352
- - **Persistence:** Data persists across overlay reloads and is shared between all overlay clients connected to the same Lumia Stream instance.
353
- - **Use Case:** Storing overlay-specific state or data that needs to be shared between multiple overlay clients or sessions.
354
- - **Limitations:**
355
- - Not accessible by Lumia Stream commands or chatbots (only overlays can read/write).
356
- - Not synced to the cloud or between different Lumia Stream servers.
320
+ - **Scope:** Triggers a Lumia command that can then update variables or run any Lumia action.
321
+ - **Use Case:** Let a command own the logic (e.g., loyalty-point math, chatbot replies) while the overlay just invokes it.
357
322
 
358
323
  #### Summary Table
359
324
 
360
- | Method | Scope/Access | Persistence | Accessible By | Best For |
361
- | -------------------------- | --------------------------- | --------------- | ------------------ | ----------------------------------------- |
362
- | `localStorage` | Per browser/tab | Browser reloads | Overlay only | User preferences, local state |
363
- | Lumia Stream Variables | Global (Lumia Stream) | Server-wide | Overlays, commands | Shared/global state, cross-feature access |
364
- | `Overlay.callCommand` | Custom (via command logic) | Custom | Overlay & commands | Advanced workflows, custom logic |
365
- | `Overlay.saveStorage` etc. | Per overlay `codeId`/server | Server (local) | Overlays only | Overlay-specific persistent data |
325
+ | Method | Scope | Accessible By | Best For |
326
+ | -------------------------- | --------------------------- | ------------------ | ----------------------------------------- |
327
+ | Lumia Stream Variables | Global (Lumia Stream) | Overlays, commands | Shared/global state, cross-feature access |
328
+ | `Overlay.saveStorage` etc. | Per overlay `codeId`/server | Overlays only | Overlay-specific persistent data |
329
+ | `Overlay.callCommand` | Custom (via command logic) | Overlay & commands | Advanced workflows, custom logic |
366
330
 
367
- > **Tip:** Choose the storage method that best fits your data's scope and persistence needs. For most overlay-to-overlay communication, use variables or `saveStorage`. For global state, prefer variables. For overlay-local state, use `localStorage` or `saveStorage`.
331
+ > **Tip:** Use Variables when other Lumia features need the value; use `Overlay.saveStorage` when only the overlay needs it.
368
332
 
369
333
  ---
370
334
 
@@ -745,6 +709,8 @@ You can display the value of a variable or storage item in your overlay by direc
745
709
 
746
710
  Variables can be used in these examples
747
711
 
712
+ In CSS, leave color/size/number variables unquoted. In JS, put replacement tokens inside quotes and parse numbers manually when needed.
713
+
748
714
  HTML Tab
749
715
 
750
716
  ```html
@@ -819,7 +785,10 @@ Lumia Stream allows you to send data from your application to the overlay. This
819
785
 
820
786
  ```js
821
787
  async function() {
822
- overlaySendCustomContent({ codeId: "mycode", content: '{"type": "add", "value": "{{username}} - {{message}}"' });
788
+ overlaySendCustomContent({
789
+ codeId: "mycode",
790
+ content: JSON.stringify({ type: "add", value: "{{username}} - {{message}}" })
791
+ });
823
792
 
824
793
  // Make sure you call done() to avoid memory leaks
825
794
  done();
@@ -829,9 +798,9 @@ async function() {
829
798
  Then in your Custom Overlay JS Tab you would listen to it and parse it with:
830
799
 
831
800
  ```js
832
- Overlay.on('overlaycontent', (data) => {
801
+ Overlay.on("overlaycontent", (data) => {
833
802
  const content = JSON.parse(data.content);
834
- toast('This is for my code', content);
803
+ toast(`This is for my code: ${content.value}`);
835
804
  });
836
805
  ```
837
806