@happyvertical/smrt-svelte

Svelte 5 component library for SMRT: Provider, hooks, browser AI (STT/TTS/LLM with warm cache), dual theme system, permission-aware rendering, and module UI registry.

v0.20.44Svelte 5RunesBrowser AI

Overview

@happyvertical/smrt-svelte is the UI package for the SMRT framework. It provides a root Provider component, 7 hooks, 56+ Svelte 5 components across 14 subdirectories, browser-based AI adapters with warm client cache, a dual theme system, permission actions, and a module UI registry for cross-package component discovery.

Key Capabilities

  • Provider: Root component wrapping your app in +layout.svelte -- provides auth state, permissions, WebSocket, and AI capabilities
  • 7 Hooks: useAuth, useSocket, useAppState, useSTT, useTTS, useLLM, useTheme
  • Browser AI: STT (browser-speech, whisper-cpp, whisper-wasm), TTS (browser-synthesis), LLM (webllm, transformers-llm) with preload strategies and warm client cache that survives navigation
  • Permission system: PermissionCheck component and use:permission action for permission-aware rendering
  • Dual theme system: Simple ThemeProvider with design tokens, plus full preset system (material/glass/studio) with CSS generation and runtime switching via ThemeSwitcher
  • Module UI Registry: Cross-package component discovery for agent admin panels
  • Ripple action: Material-style use:ripple for interactive feedback

Installation

bash
pnpm add @happyvertical/smrt-svelte

Peer dependencies (all optional): svelte >=5.18.2, @happyvertical/smrt-agents, @happyvertical/smrt-jobs, @happyvertical/smrt-profiles, @happyvertical/smrt-users.

Quick Start

Provider Setup

svelte
<!-- +layout.svelte -->
<script>
  import { Provider } from '@happyvertical/smrt-svelte';
  let { data, children } = $props();
</script>

<Provider user={data.user} permissions={data.permissions}
  ai={{ preload: 'idle', stt: { type: 'whisper-cpp' } }}>
  {@render children()}
</Provider>

Using Hooks

svelte
<script>
  import { useAuth, useSTT } from '@happyvertical/smrt-svelte';

  const { user, isAuthenticated, hasPermission } = useAuth();
  const { start, stop, isListening, lastResult } = useSTT();
</script>

{#if isAuthenticated}
  <p>Hello, {user.displayName}</p>
  <button onclick={() => isListening ? stop() : start()}>
    {isListening ? 'Stop' : 'Listen'}
  </button>
  <p>{lastResult}</p>
{/if}

Subpath Exports

The package uses subpath exports to organize components by category. Import from the specific subpath for tree-shaking.

Import PathContents
@happyvertical/smrt-svelteProvider, DataTable, permission utilities, hooks, state, core components
@happyvertical/smrt-svelte/adminAgentAdminPanel, AgentAdminTabs, AgentSettingsShell
@happyvertical/smrt-svelte/calendarCalendar, DayView
@happyvertical/smrt-svelte/formsTextInput, Select, MoneyInput, DateTimeInput, Toggle, FileUpload, AddressInput, and more
@happyvertical/smrt-svelte/layoutContainer, Grid, Header, Footer, Masthead, PageHeader, EmptyState, SummaryCard
@happyvertical/smrt-svelte/uiButton, Card, Badge, Pagination
@happyvertical/smrt-svelte/themesThemeProvider, presets (material/glass/studio), CSS generation
@happyvertical/smrt-svelte/registryModuleUIRegistry for agent admin panels
@happyvertical/smrt-svelte/browser-aiBrowser AI client (STT/TTS/LLM adapters, capability detection)
@happyvertical/smrt-svelte/browser-ai/svelteSvelte AI components (VoiceInput, CapabilityGate, DownloadProgress, etc.)
@happyvertical/smrt-svelte/styles/tokens.cssDesign tokens CSS

Component Categories

56+ components organized across 14 subdirectories. See the component catalog for individual component documentation.

CategoryDescription
FormsTextInput, Select, MoneyInput, DateTimeInput, Toggle, FileUpload, AddressInput, PhoneInput, NumberInput, DateRangeInput, MeasurementInput, SearchInput, Textarea, CheckboxInput, and more
LayoutContainer, Grid, Header, Footer, Masthead, PageHeader, EmptyState, SummaryCard
UIButton, Card, Badge, Pagination
DisplayConfidenceBadge, CurrencyDisplay, DateDisplay, Icon, StatusBadge
FeedbackConfirmDialog, LoadingOverlay, Modal, ProgressBar
NavigationFilterChips, Tabs
DataDataTable
PermissionsPermissionCheck, RoleBadge, RoleSelector
AdminAgentAdminPanel, AgentAdminTabs, AgentSettingsShell
CalendarCalendar, DayView
MembershipsMembershipCard, MembershipList
ModuleModulePanel
RolesRoleBadge, RoleSelector
ThemeThemeProvider, ThemeSwitcher

Browser AI

The browser AI system (previously a separate browser-ai package, consolidated in v0.20) provides on-device speech-to-text, text-to-speech, and LLM inference. A module-level warm client cache (Map) survives navigation and remounts, avoiding re-downloading WASM modules and AI models.

Preload Strategies

  • none -- load on first use
  • eager -- load immediately on mount
  • idle -- load when browser is idle (recommended)
  • on-visible -- load when component enters viewport

Cache API

typescript
import { getCachedSTT, getCachedTTS, getCachedLLM, getCacheStats, clearAllCaches }
  from '@happyvertical/smrt-svelte/browser-ai';

// Check what's loaded
const stats = getCacheStats();
console.log(stats); // { stt: true, tts: false, llm: true }

// Get a cached adapter (returns undefined if not loaded)
const stt = getCachedSTT();

Permission-Aware Rendering

svelte
<script>
  import { PermissionCheck, permission } from '@happyvertical/smrt-svelte';
</script>

<!-- Component-based -->
<PermissionCheck requires="admin:write">
  <button>Admin Action</button>
</PermissionCheck>

<!-- Action-based (hides or disables element) -->
<div use:permission={{ slug: 'articles.delete', permissions: userPermissions }}>
  Delete
</div>
<div use:permission={{ slug: 'articles.delete', permissions: userPermissions, hideOnly: true }}>
  Delete (hidden if no permission)
</div>

Theme System

Two theme systems for different levels of customization:

  • src/theme/: Simple ThemeProvider with design tokens
  • src/themes/: Full preset system with material, glass, and studio presets, CSS generation, and runtime switching
svelte
<script>
  import { ThemeProvider } from '@happyvertical/smrt-svelte/themes';
</script>

<ThemeProvider preset="glass" colorScheme="system">
  {@render children()}
</ThemeProvider>