Trixie
◇TRIXIE
{connectionState}{#if connectionNotice}{connectionNotice}{/if}{#if authenticated}
{#if showNotifications}
NOTIFICATIONS
{#if notifications.length}{#each notifications as notification}
{notification.title}{notification.severity}
{notification.message}
{#if !notification.seen_at}{/if}
{/each}{:else}
No notifications.
{/if}
{/if}
{/if}
{#if !authenticated}
AUTHENTICATION REQUIRED
⌁
Sign in to TrixieThe server connection is ready, but the dashboard requires administrator authentication.
{:else if mustReplaceCredentials}
FIRST-RUN SETUP
Replace the generated administrator credentials {#if authError}
{authError}
{/if}
{:else if activeView === 'Bot'}
{commandFormId ? 'EDIT COMMAND' : 'NEW COMMAND'}
BOT COMMANDS
PUBLIC COMMAND CATALOG
{#if botCommandError}
{botCommandError}
{:else if botCommands.length}
{#each botCommands as command}
!{command.name}{command.description}{#if command.tags.length}
{command.tags.join(' · ')}
{/if}
{command.permission_level.toUpperCase()}{#if command.cooldown_seconds}{command.cooldown_seconds}s / {command.cooldown_scope}{/if}
{/each}
{:else}
No enabled commandsCreate commands on the server to make them available here.
{/if}
SECRETS MANAGEMENT
Values are encrypted and cannot be read after saving.
{#if botSecrets.length}
{#each botSecrets as secret}
{secret.name}{secret.description || 'No description'}{#if secret.used_by.length}
USED BY: {secret.used_by.join(', ')}
{/if}
{/each}
{:else}
There are no secrets yet.
{/if}{#if secretError}
{secretError}
{/if}
COMMAND MANAGEMENT
{#each botCommands as command}
!{command.name}{command.enabled ? 'ENABLED' : 'DISABLED'} · {command.permission_level.toUpperCase()}
{/each}{#if !botCommands.length}
No commands are configured yet.
{/if}
{:else if activeView === 'Overlays'}
OVERLAYS
{#if selectedOverlayId || overlayName}
LIVE PREVIEW
{#if overlayError}
{overlayError}
{/if}{:else}
Select or create an overlayDrafts autosave when explicitly saved; publishing controls the browser source.
{/if}
{:else if activeView === 'Settings'}
SERVER SETTINGS
DATABASE BACKUPS

Daily backups use the server's local schedule. Restore remains a destructive recovery workflow and is not started from this list.

{#if backupError}
{backupError}
{/if}{#if backups.length}
{#each backups as backup}
{backup.filename}{Math.round(backup.size_bytes / 1024)} KiB{backup.modified_at ? new Date(backup.modified_at).toLocaleString() : 'UNKNOWN TIME'}
{/each}
{:else}
No backup archives are available.
{/if}
{:else}
STREAM PREVIEW⋮
{#if playerSrc}{:else}
STREAM OFFLINE
CONNECT TWITCH TO BEGIN
{/if}
ACTIVITY FEED⋮
{#if activityEvents.filter((event) => activityFilter === 'all' || event.event_type.startsWith('moderation.')).length}
{#each activityEvents.filter((event) => activityFilter === 'all' || event.event_type.startsWith('moderation.')) as event}
{event.event_type}{new Date(event.occurred_at).toLocaleTimeString()}
{/each}
{:else}
◌
Nothing here yet{activityFilter === 'moderation' ? 'Moderation events will appear here.' : 'Follows, subscriptions, raids, and server events will appear here.'}
{/if}
MY CHAT⋮
{#if pinnedMessageIds.length}
PINNED{#each chatMessages.filter((message) => pinnedMessageIds.includes(message.message_id)) as message}
{message.user_name}{message.text}
{/each}
{/if}{#if chatMessages.length}
{#each chatMessages as message}
{#if message.fragments.length}{#each message.fragments as fragment}{#if fragment.type === 'emote' && fragment.emote_id}{fragment.text}{:else}{fragment.text}{/if}{/each}{:else}{message.text}{/if}
{/each}
{:else}
⌁
Chat is waitingConnect a streamer or bot account to begin.
{/if}
{#if chatReplyParent}
REPLYING TO @{chatReplyParent.user_name}
{/if}
{#if chatEmoteOptions.length}
{#each chatEmoteOptions as emote}{/each}
{/if}
searchChatEmotes(chatMessage)} onkeydown={(event) => event.key === 'Enter' && sendChatMessage()} />
{#if chatError}
{chatError}
{/if}
QUICK ACTIONS⋮
{#if showCollaboration}
GUEST STAR SESSION
{#if collaborationSession}
ACTIVE · {collaborationSession.guests.length} GUESTS
{#if collaborationInvites.length}
PENDING INVITES
{#each collaborationInvites as invite}
{invite.user_id} · {invite.status}
{/each}{/if}{:else}
No active collaboration.
{/if}{#if collaborationError}
{collaborationError}
{/if}
{/if}{#if showStreamEditor}
searchCategories(event.currentTarget.value)} autocomplete="off" placeholder="Search Twitch categories" />{#if categoryOptions.length}
{#each categoryOptions as category}{/each}
{/if}{#if streamError}
{streamError}
{/if}
{/if}{#if showModeration}
{#if moderationError}
{moderationError}
{/if}
{/if}
{/if}
{#if authenticated && showCollaboration}
COLLABORATOR SEARCH⋮
searchCollaborators(event.currentTarget.value)} autocomplete="off" placeholder="Search Twitch" />
{#if collaboratorSearchBusy}
SEARCHING TWITCH…
{/if} {#if collaboratorSearchError}
{collaboratorSearchError}
{/if} {#if collaboratorResults.length}
{#each collaboratorResults as result}
{result.display_name} @{result.login}
{/each}
{:else if collaboratorSearch && !collaboratorSearchBusy && !collaboratorSearchError}
No exact Twitch user found.
{/if}
FAVORITES & RECENT
{#if collaborators.length}
{#each collaborators as collaborator}
{collaborator.display_name}
{/each}
{:else}
No saved collaborators yet.
{/if}
{/if} {#if chatMessages.some((message) => message.reply_parent_message_id)}
CHAT THREADS
{#each chatMessages.filter((message) => message.reply_parent_message_id) as reply} {@const root = chatMessages.find((message) => message.message_id === reply.reply_parent_message_id)} {#if root}{/if} {/each}
{/if} {#if chatThreadRoot}
THREAD · @{chatThreadRoot.user_name}
{chatThreadRoot.user_name}{chatThreadRoot.text}
{#each chatMessages.filter((message) => message.reply_parent_message_id === chatThreadRoot?.message_id) as reply}
{reply.user_name}{reply.text}
{:else}
No replies received yet.
{/each}
{/if} {#if pendingOverlayDraft}
LOCAL OVERLAY DRAFT FOUND
A newer unsaved draft is available for this overlay.
{/if} {#if activeView === 'Overlays' && selectedOverlayId}
OVERLAY LIFECYCLE
DELETION IS PERMANENT AND INVALIDATES THE BROWSER-SOURCE URL
{/if} {#if activeView === 'Overlays' && (selectedOverlayId || overlayName) && overlayVariableWarnings().length}
{#if overlayDiagnosticsOpen}
{#each overlayVariableWarnings() as warning}
{warning}
{/each}
{/if}
{/if} {#if !authenticated && publicBotCommands.length}
PUBLIC BOT COMMANDS
AVAILABLE COMMANDS
{#each publicBotCommands as command}
!{command.name}{command.description}{#if command.tags.length}
{command.tags.join(' · ')}
{/if}
{command.permission_level.toUpperCase()}
{/each}
{/if}