Migration Guide: 0.19 to 0.20+
Version 0.20 reorganizes Svelte components into their domain packages and consolidates browser-ai into smrt-svelte. This guide covers all breaking changes through 0.20.44.
Component Import Changes
Domain-specific components have moved from @happyvertical/smrt-svelte to their
respective package's /svelte subpath. Core UI components (forms, layout, feedback,
themes) remain in smrt-svelte.
Users
// Before
import { UserCard, UserAvatar, UserList } from '@happyvertical/smrt-svelte';
// After
import { UserCard, UserAvatar, UserList } from '@happyvertical/smrt-users/svelte';Commerce
// Before
import { InvoiceCard, InvoiceLineItems } from '@happyvertical/smrt-svelte';
// After
import { InvoiceCard, InvoiceLineItems } from '@happyvertical/smrt-commerce/svelte';Tenancy
// Before
import { TenantSwitcher, TenantCard } from '@happyvertical/smrt-svelte';
// After
import { TenantSwitcher, TenantCard } from '@happyvertical/smrt-tenancy/svelte';Jobs
// Before
import { JobDashboard, JobList } from '@happyvertical/smrt-svelte';
// After
import { JobDashboard, JobList } from '@happyvertical/smrt-jobs/svelte';Agents
// Before
import { AgentDashboard, AgentRunHistory } from '@happyvertical/smrt-svelte';
// After
import { AgentDashboard, AgentRunHistory } from '@happyvertical/smrt-agents/svelte';Content
// Before
import { ArticleCard, ArticleList } from '@happyvertical/smrt-svelte';
// After
import { ArticleCard, ArticleList } from '@happyvertical/smrt-content/svelte';Events
// Before
import { MeetingView } from '@happyvertical/smrt-svelte';
// After
import { MeetingView } from '@happyvertical/smrt-events/svelte';Projects
// Before
import { TimeEntryCard, ApprovalActions } from '@happyvertical/smrt-svelte';
// After
import { TimeEntryCard, ApprovalActions } from '@happyvertical/smrt-projects/svelte';What stays in smrt-svelte
These categories remain in @happyvertical/smrt-svelte:
- Forms (TextInput, Select, DateTime, etc.)
- Layout (PageHeader, Grid, EmptyState, etc.)
- Feedback (Modal, ConfirmDialog, ProgressBar)
- Navigation (Tabs, FilterChips)
- Display (StatusBadge, CurrencyDisplay, DateDisplay)
- Themes (ThemeSwitcher, ColorSchemeToggle)
- AI components (VoiceInput, DownloadProgress, AILoadingOverlay)
- Hooks (useSTT, useTTS, useLLM, useAuth, useSocket)
- Provider, permissions, roles, memberships
browser-ai Consolidated
The standalone @happyvertical/browser-ai package has been merged into @happyvertical/smrt-svelte. Remove the browser-ai dependency and update imports:
// Before
import { BrowserAI } from '@happyvertical/browser-ai';
import type { STTAdapter, TTSAdapter } from '@happyvertical/browser-ai';
// After — use hooks instead
import { useSTT, useTTS, useLLM } from '@happyvertical/smrt-svelte';TenantSwitcher API Change
The TenantSwitcher component now accepts a Map of tenants and a
separate memberships array, and uses onchange instead of onswitch:
// Before
<TenantSwitcher
tenants={tenantsArray}
currentTenantId={id}
onswitch={handleSwitch}
/>
// After
<TenantSwitcher
tenants={tenantsMap}
memberships={memberships}
currentTenantId={id}
onchange={handleSwitch}
/>MembershipCard / MembershipList API Change
These components now accept separate tenant and role props instead
of embedding them in the membership object:
// Before
<MembershipCard membership={membershipWithEverything} />
// After
<MembershipCard {membership} {tenant} {role} />
// MembershipList uses MembershipWithContext objects
<MembershipList memberships={[
{ membership, tenant, role },
...
]} />PermissionCheck API Change
PermissionCheck now requires an explicit userPermissions array
and uses a Snippet for fallback content:
// Before
<PermissionCheck permission="users.edit" fallback="No access">
<button>Edit</button>
</PermissionCheck>
// After
<PermissionCheck permission="users.edit" userPermissions={currentPermissions}>
{#snippet fallback()}<span>No access</span>{/snippet}
<button>Edit</button>
</PermissionCheck>Profiles: Tenancy Peer Dependency
@happyvertical/smrt-profiles now lists @happyvertical/smrt-tenancy as a peer dependency. Install it if you use multi-tenant features:
pnpm add @happyvertical/smrt-tenancyCSS Custom Properties
All theme tokens now use the --smrt-color-* prefix following Material Design 3
naming. If you were using older token names, update to the new prefix:
/* New token format */
--smrt-color-primary
--smrt-color-on-primary
--smrt-color-primary-container
--smrt-color-surface
--smrt-color-surface-variant
--smrt-color-outlinePost-0.20.0 Changes (through 0.20.44)
CLI Migration Commands
Migration commands have been updated. The old smrt migrations generate syntax
is replaced:
# Generate migration from schema changes
smrt db:diff --generate
# Check pending schema changes
smrt db:status
# Apply migrations
smrt db:migrate
# Rollback migrations
smrt db:rollbackConfig Shape
The smrt.config.ts top-level keys have been reorganized.
Replace old database/api/cli/mcp keys
with the new structure:
import { defineConfig } from '@happyvertical/smrt-config';
// Before (old shape - no longer valid)
export default defineConfig({
database: { type: 'postgresql', host: '...' },
api: { enabled: true, port: 3000 },
cli: { enabled: true },
mcp: { enabled: true, port: 3100 }
});
// After (current shape)
export default defineConfig({
smrt: {
logLevel: 'info',
environment: 'production',
embeddings: { provider: 'local' }
},
modules: {
'my-agent': { cronSchedule: '0 2 * * *' }
},
packages: {
ai: { defaultModel: 'gpt-4o' }
}
});Agent Signal Handling
Agents now automatically register SIGTERM/SIGINT handlers during initialize() for graceful shutdown. If you had custom signal handling, it is now built-in. Always call super.shutdown() to clean up signal handlers.
Relationship Decorators
Relationship fields (foreignKey, oneToMany, manyToMany)
are now decorators, not plain assignment helpers:
// Before (plain assignment - no longer valid)
class Order extends SmrtObject {
customerId = foreignKey(Customer);
items = oneToMany(OrderItem);
}
// After (decorators)
class Order extends SmrtObject {
@foreignKey(Customer)
customerId: string = '';
@oneToMany(OrderItem)
items: OrderItem[] = [];
}Collection _itemClass
The _itemClass static property must now be readonly:
// Before
class MyCollection extends SmrtCollection<MyObject> {
static itemClass = MyObject;
}
// After
class MyCollection extends SmrtCollection<MyObject> {
static readonly _itemClass = MyObject;
}