@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.
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:
PermissionCheckcomponent anduse:permissionaction 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:ripplefor interactive feedback
Installation
pnpm add @happyvertical/smrt-sveltePeer dependencies (all optional): svelte >=5.18.2, @happyvertical/smrt-agents, @happyvertical/smrt-jobs, @happyvertical/smrt-profiles, @happyvertical/smrt-users.
Quick Start
Provider Setup
<!-- +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
<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 Path | Contents |
|---|---|
@happyvertical/smrt-svelte | Provider, DataTable, permission utilities, hooks, state, core components |
@happyvertical/smrt-svelte/admin | AgentAdminPanel, AgentAdminTabs, AgentSettingsShell |
@happyvertical/smrt-svelte/calendar | Calendar, DayView |
@happyvertical/smrt-svelte/forms | TextInput, Select, MoneyInput, DateTimeInput, Toggle, FileUpload, AddressInput, and more |
@happyvertical/smrt-svelte/layout | Container, Grid, Header, Footer, Masthead, PageHeader, EmptyState, SummaryCard |
@happyvertical/smrt-svelte/ui | Button, Card, Badge, Pagination |
@happyvertical/smrt-svelte/themes | ThemeProvider, presets (material/glass/studio), CSS generation |
@happyvertical/smrt-svelte/registry | ModuleUIRegistry for agent admin panels |
@happyvertical/smrt-svelte/browser-ai | Browser AI client (STT/TTS/LLM adapters, capability detection) |
@happyvertical/smrt-svelte/browser-ai/svelte | Svelte AI components (VoiceInput, CapabilityGate, DownloadProgress, etc.) |
@happyvertical/smrt-svelte/styles/tokens.css | Design tokens CSS |
Component Categories
56+ components organized across 14 subdirectories. See the component catalog for individual component documentation.
| Category | Description |
|---|---|
| Forms | TextInput, Select, MoneyInput, DateTimeInput, Toggle, FileUpload, AddressInput, PhoneInput, NumberInput, DateRangeInput, MeasurementInput, SearchInput, Textarea, CheckboxInput, and more |
| Layout | Container, Grid, Header, Footer, Masthead, PageHeader, EmptyState, SummaryCard |
| UI | Button, Card, Badge, Pagination |
| Display | ConfidenceBadge, CurrencyDisplay, DateDisplay, Icon, StatusBadge |
| Feedback | ConfirmDialog, LoadingOverlay, Modal, ProgressBar |
| Navigation | FilterChips, Tabs |
| Data | DataTable |
| Permissions | PermissionCheck, RoleBadge, RoleSelector |
| Admin | AgentAdminPanel, AgentAdminTabs, AgentSettingsShell |
| Calendar | Calendar, DayView |
| Memberships | MembershipCard, MembershipList |
| Module | ModulePanel |
| Roles | RoleBadge, RoleSelector |
| Theme | ThemeProvider, 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 useeager-- load immediately on mountidle-- load when browser is idle (recommended)on-visible-- load when component enters viewport
Cache API
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
<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 tokenssrc/themes/: Full preset system with material, glass, and studio presets, CSS generation, and runtime switching
<script>
import { ThemeProvider } from '@happyvertical/smrt-svelte/themes';
</script>
<ThemeProvider preset="glass" colorScheme="system">
{@render children()}
</ThemeProvider>