Skip to content

Documentation

Widget Loader

Dynamic async widget component loader with code-splitting, error boundaries, and Valibot validation.

6/27/2026
2 min read Edit on GitHub
On this page

The Widget Loader enables dynamic, asynchronous loading of widget components with code-splitting. Widgets are loaded on-demand rather than bundled upfront, improving initial bundle size and time-to-interactive.

Props

Prop Type Default Description
loader () => Promise<{ default: any }> required Dynamic import function for the widget component
field FieldInstance required Field configuration from the collection schema
value any Current field value for binding
tenantId string \| null Multi-tenant isolation scope
collectionName string Parent collection name for context
WidgetData Record<string, any> {} Additional widget configuration data
onFieldSync () => void Callback fired on value change — patches parent store field-by-field (avoids full-form JSON.stringify)

Features

  • Code-Splitting: Widget components imported via dynamic loader() function, enabling per-widget lazy loading
  • Valibot Runtime Validation: When a widget defines a validationSchema, values are validated at runtime with safeParse()
  • Error Boundary: Catches widget load failures and renders a fallback UI with retry capability
  • Field-Store Sync: The onFieldSync callback lets parent components patch individual fields without serializing the entire form
  • Svelte 5 Runes: Uses $state(), $derived(), and $effect() for reactive updates

Usage

<WidgetLoader
  loader={() => import("./widgets/my-widget/input.svelte")}
  {field}
  bind:value={entryValue}
  tenantId={locals.tenantId}
/>

Related

componentsarchitecturewidgets
Was this page helpful?