SnowLuma WebUI
SnowLuma's browser console is a Vite + React application for managing runtime status, OneBot configuration, logs, storage, and server settings.
Default appearance
New installations and appearance resets use the mascot's lavender accent. The light variant uses a deeper purple for readable button labels; dark mode uses a softer lavender. Existing saved accents and custom colors are preserved. The original sky-blue accent remains available in Settings.
With the default palette, page, card, input, popover and sidebar surfaces mix a small amount of the active accent into neutral light/dark backgrounds. Text stays neutral for readability. Sidebar-only accents tint only the sidebar; OLED keeps a true-black canvas. Named palettes, custom CSS variables and host appearance overlays retain control of their own surfaces.
Keep the server defaults in packages/core/src/webui/ui-config.ts, the frontend
defaults and preset in src/contexts/ThemeContext.tsx, and the pre-mount tokens
in src/index.css aligned when changing the default accent.
The browser favicon, home-screen icon and in-app logo share the mascot avatar
in assets/brand/mascot-avatar.png.
Its exported sizes live in public/: logo.png (512 px), favicon.png (64 px),
and apple-touch-icon.png (180 px). Export from the master without redrawing
individual sizes.
Host appearance integration
SNOWLUMA_WEBUI_TARGET=maibot opts a deployment into a reversible millennium
appearance overlay. Standalone defaults are unchanged. Hosts drive live light/dark
updates without saving over personal preferences or adding another selector.
See the integration contract and extension guide before changing
target startup, theme ownership, host messaging or scoped styles.
Interaction conventions
- Destructive actions and second confirmations stay in modal dialogs.
- Operations that may take time show a bottom-right running state.
- Completed and failed operations use bottom-right result notices that close automatically after a visible countdown.
- Routine, high-frequency adjustments should not generate a notice for every intermediate edit.
- Foreground polling pauses in hidden tabs and waits for each request to finish before scheduling the next. Connection-state polling runs only while SSE clients are subscribed.
- Data-backed surfaces use the Interior Skeleton Swap defaults (120 ms delay, 380 ms minimum visibility) so fast local responses do not flash a placeholder. Submission, upload, and other explicit operation progress keeps its spinner.
- Variable-height content must release the skeleton's reserved box after it is ready; do not introduce a second scrolling region inside the page.
- The mobile navigation menu uses a controlled Icon Morph whose visual state follows the actual drawer state.
- Failures must remain visible in the affected control and in the operation result; do not convert failed responses into successful feedback.
- JSON endpoints must return an object. Malformed or non-object responses are reported as errors rather than displayed as empty lists or default settings.
- Configuration responses include
config; saves also reportsaved,applied,online,errors, andmessage. The UI uses these fields without legacy aliases or a second request after saving. - Password change flows use floating labels and inline validation consistently.
- Password strength details appear only while the new-password field has focus and leave with the same motion language when focus moves away.
- The first-run wizard keeps agreement text as the primary reading surface and aligns each step's actions inside one responsive footer. Settings includes a visible developer page for safely replaying this wizard and exercising the page-level crash screen; replayed consent and passwords are never persisted.
Authentication behind a reverse proxy
Authenticated WebUI requests send the session token in X-SnowLuma-Token, leaving
Authorization available for the reverse proxy's HTTP authentication (such as
Nginx Basic Auth). Forward X-SnowLuma-Token unchanged if the proxy filters
request headers. The backend still accepts Authorization: Bearer <token> for
existing clients when the dedicated header is absent. Both layers still require
their own valid credentials.
Late authentication failures from an old session do not sign out a newer session. Live streams release subscriptions on disconnect and pause with the page. Malformed stream data is reported; a debug stream invocation fails instead of silently succeeding.
Process account detection
Process cards use QQ's local account data before injection and the hook's confirmed
identity after login. Missing local data means the account is unknown. It does not
prove that QQ is signed out, and local detection alone never marks a bridge online.
The manual login probe and /api/processes/:pid/probe-login endpoint are removed.
Linux resolves data roots from each QQ process's XDG_CONFIG_HOME or HOME.
Windows uses the bundled addon’s getFileHoldersAsync to find the process holding
each account database. Query failures are reported instead of treated as no login.
Account notification templates
Webhook bodies and email subjects/bodies support {uin}, {nickname}, {event}
(offline or online), {time}, {status} (Hook process state), {pid}, and
{error} (Hook process error). New webhook and email channels include process
status in their default body; existing saved templates are preserved.
JSON templates escape substituted strings, including quotes, line breaks and control characters.
Process facts are resolved when the notification is dispatched, after any offline debounce. Each transition carries its process PID, including the final PID detached when an account goes offline. Facts are looked up for that PID and UIN without substituting another process. Missing facts render empty and mean unknown, not proof that QQ exited. Hook status alone does not identify the cause of a QQ login failure. Notifications for one account are delivered in transition order; a slow account does not delay other accounts.
Local development
Packaged installations offer download and restart controls in Settings → About. Downloads are verified and staged; files are applied before the application starts. Restart confirmation uses the shared modal, and download results use action feedback.
On Windows, the native API logs the process token and EXE integrity label once at startup. A Low (or lower) token triggers a WebUI warning; file labels and query failures alone do not. “临时关闭” lasts for the tab session, including reloads; “永久关闭” persists in this browser's site storage. Neither suppresses startup logs. Failed queries and preference writes remain visible.
From the repository root:
pnpm --filter webui dev
pnpm --filter webui typecheck
pnpm --filter webui lint
pnpm --filter webui test
pnpm --filter webui build