diff --git a/CHANGELOG.md b/CHANGELOG.md
index 439337d..881467e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,12 @@
# Lumi changelog
+## 0.2.15
+
+- Fixed Lumi's own Twitch, YouTube, and Discord messages being omitted from native chat overlays and added platform-specific plus linked-Lumi-account user blocking.
+- Replaced text platform/badge labels with platform artwork, official Twitch badge images where available, and image fallbacks for other badge types.
+- Added server-normalized unsaved source previews, temporary website-CSS previews, visible draft/revert controls, contrast backgrounds, an alignment grid, and reachable sticky source actions.
+- Hardened alert-site transparency with an optional page/root guard that remains effective when apps such as alert providers modify their document after loading.
+
## 0.2.14
- Added a native Lumi chat overlay source that combines live Twitch, YouTube, and Discord messages with optional per-channel filters.
diff --git a/TODO.md b/TODO.md
index 6efac2c..9bbfecc 100644
--- a/TODO.md
+++ b/TODO.md
@@ -28,7 +28,12 @@ Custom CSS behavior while keeping the page isolated from Lumi sessions and local
network targets. A native multi-platform Lumi chat source now combines connected
Twitch, YouTube, and Discord chats with channel filters, full visual controls,
animations, timeout removal, short reconnect replay, Twitch emotes, and isolated
-custom CSS.
+custom CSS. The editor now previews server-normalized unsaved changes (including
+temporary website CSS), marks/reverts drafts, provides contrast and grid views,
+and keeps save actions reachable. Alert documents also retain transparent page
+and app-root backgrounds after late DOM/style changes. Chat includes Lumi's own
+platform messages, image-based platform/badge marks, and server-enforced platform
+or linked-Lumi-account user blocking.
Remaining work:
@@ -686,6 +691,8 @@ This section is for Lumi chat answer feedback and AI Improvement Center work, no
## Done
+- 2026-07-19: Fixed native chat overlays to include Lumi's own platform messages; added `platform:username|id` and linked `lumi:username|id` blocking before scoped delivery; replaced text platform/badge labels with images and official Twitch badge catalog artwork; added normalized unsaved source previews, secured website-CSS drafts, visible dirty/revert state, sticky save controls, contrast backgrounds, and a placement grid; and hardened transparency against late-loading alert-app DOM/style changes.
+
- 2026-07-19: Added the native Lumi chat overlay source with combined Twitch, YouTube, and Discord messages; optional platform/channel filters; avatars, badges, Twitch emotes, timestamps, typography, transparent colors, alignment and spacing; entry/exit animations; bounded timeout/capacity removal; isolated CSS; representative editor previews; and short-lived reconnect replay through the existing scoped overlay event stream.
- 2026-07-18: Replaced frame-only website styling with OBS-style document CSS injection. External alert pages now receive OBS's transparent body CSS by default plus administrator selectors inside the website document; scoped revocable source tickets, opaque sandboxing, no-referrer handling, bounded public fetching, and private-network blocking protect Lumi and its overlay secrets.
diff --git a/docs/obs-overlays.md b/docs/obs-overlays.md
index d61c3a5..b417bbd 100644
--- a/docs/obs-overlays.md
+++ b/docs/obs-overlays.md
@@ -80,6 +80,18 @@ top-or-bottom placement, timeout removal, and separate entry and exit
animations. Twitch emotes are displayed as images. The editor canvas supplies
sample messages so appearance can be configured before the stream is live.
+Lumi includes messages sent by its own connected bot accounts. Platform marks
+are shown as icons, and chat badges are rendered as images. Twitch badge artwork
+is resolved from Twitch's global and channel badge catalogs; a local image
+fallback is used when a provider does not expose badge artwork.
+
+The optional hidden-user list accepts one rule per line in the form
+`platform:username|user-id`. Twitch, YouTube, and Discord rules match only that
+platform. A `lumi:internal-name|user-id` rule uses Lumi's linked identity model,
+so one rule hides every connected platform identity belonging to that Lumi user.
+Filtering is enforced before a message enters an overlay's scoped event stream
+and is also checked by the renderer.
+
Advanced CSS is isolated to that chat source and is appended after the visual
settings. Stable selectors include `.chat`, `.message`, `.avatar`, `.content`,
`.meta`, `.platform`, `.author`, `.badge`, `.timestamp`, `.text`, and `.emote`.
@@ -134,6 +146,12 @@ compatibility mode is available for private/local pages and unusual sites that
cannot run through document injection; direct mode intentionally cannot change
cross-origin page content.
+**Keep the website background transparent** is enabled by default. It protects
+the page, body, and common application roots with a transparent background and
+reapplies that protection when a late-loading alert application changes its DOM
+or inline styles. It can be disabled for a website that intentionally needs an
+opaque page background.
+
Lumi applies OBS's standard transparent Browser Source CSS to every clean render
page and shows the same copyable value in the Browser Source setup section:
@@ -145,6 +163,21 @@ The Lumi document, canvas stage, embedded frame surface, and injected website
body are transparent by default. Administrators can extend or override the
default stylesheet per source just as they do in OBS Browser Source properties.
+## Visual editing workflow
+
+Existing sources use a draft preview workflow. Changing a field sends the draft
+through the same server normalizer used for saving and updates the canvas after a
+short delay without changing the stored source. Website URLs and CSS receive a
+short-lived, access-controlled preview document, so their unsaved appearance is
+also visible. Each changed card is marked as unsaved and offers **Save source**
+or **Undo unsaved changes**.
+
+The preview can switch between transparency checkerboard, dark, and light
+backgrounds to expose unwanted opaque areas or low-contrast text. An optional
+grid adds five-percent lines and canvas midpoints. Source save controls remain
+sticky at the bottom of long settings panels, while drag, resize, keyboard
+nudge, anchors, snapping, crop, zoom, and precise number fields remain available.
+
## OBS WebSocket
The connector is disabled by default. Enable OBS WebSocket in OBS, keep its
diff --git a/knowledge/core/lumi-core.md b/knowledge/core/lumi-core.md
index b388eeb..353799f 100644
--- a/knowledge/core/lumi-core.md
+++ b/knowledge/core/lumi-core.md
@@ -14,7 +14,7 @@ editable: false
Lumi is the core web UI and bot runtime.
## Runtime
Package: lumi-bot
-Version: 0.2.14
+Version: 0.2.15
## Routes
- GET /api/events
- POST /api/destructive-confirmations
diff --git a/package-lock.json b/package-lock.json
index 1079ddf..801b709 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "lumi-bot",
- "version": "0.2.14",
+ "version": "0.2.15",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "lumi-bot",
- "version": "0.2.14",
+ "version": "0.2.15",
"dependencies": {
"adm-zip": "^0.5.12",
"better-sqlite3": "^11.5.0",
diff --git a/package.json b/package.json
index a86d422..93ee219 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "lumi-bot",
- "version": "0.2.14",
+ "version": "0.2.15",
"private": true,
"type": "commonjs",
"scripts": {
diff --git a/release-index.json b/release-index.json
index 3bde73b..ba9ce01 100644
--- a/release-index.json
+++ b/release-index.json
@@ -2,6 +2,36 @@
"schema_version": 1,
"channel": "stable",
"releases": [
+ {
+ "version": "0.2.15",
+ "ref": "refs/tags/v0.2.15",
+ "released_at": "2026-07-19",
+ "installable": true,
+ "rollback_safe": true,
+ "replaces_versions": [
+ "1.2.0"
+ ],
+ "data_policy": "preserve",
+ "dependency_policy": "sync_on_restart",
+ "migration_notes": "Improves native chat delivery, linked-user filtering and artwork, secured unsaved overlay previews, editing controls, and alert transparency. Existing overlays, tokens, scenes, sources, settings, databases, plugin data, models, uploads, feedback, and secrets are preserved.",
+ "plugins": {
+ "auto-vc": "0.1.6",
+ "birthday": "0.1.3",
+ "economy-framework": "0.2.10",
+ "economy-games": "0.1.7",
+ "expression-interaction": "0.2.1",
+ "lumi_ai": "0.8.5",
+ "moderation": "0.1.5",
+ "okf": "0.1.1",
+ "quotes": "0.1.2",
+ "sample-plugin": "0.1.0",
+ "throne_wishlist": "0.1.2",
+ "welcome_messages": "0.1.1"
+ },
+ "tools": {
+ "lumi_ai_web_search": "0.1.1"
+ }
+ },
{
"version": "0.2.14",
"ref": "refs/tags/v0.2.14",
diff --git a/scripts/verify-overlay-web-documents.js b/scripts/verify-overlay-web-documents.js
index d611550..fb0e9f8 100644
--- a/scripts/verify-overlay-web-documents.js
+++ b/scripts/verify-overlay-web-documents.js
@@ -1,7 +1,8 @@
const assert = require("assert");
const {
injectDocumentCss,
- loadInjectedOverlayDocument
+ loadInjectedOverlayDocument,
+ TRANSPARENT_WEBSITE_GUARD
} = require("../src/services/overlay-web-documents");
const { OBS_BROWSER_DEFAULT_CSS } = require("../src/services/obs-browser-defaults");
@@ -14,9 +15,20 @@ async function run() {
assert(injected.includes(''));
assert(injected.includes('`;
- const loadEndScript = loadEndCssScript(customCss);
+ const forceTransparentBackground = options.forceTransparentBackground !== false;
+ const style = ``;
+ const loadEndScript = loadEndCssScript(customCss, forceTransparentBackground);
if (/