Skip to content

Widget Builder Guide

The Widget Builder is a visual tool for creating reusable UI components (widgets) that can be embedded in your apps, pages, and flows.

Widgets are self-contained UI components that:

  • Can be customized through customization options
  • Support versioning for safe updates
  • Can be shared across your organization
  • Render natively on all platforms

  1. Open the Widget Builder

    Navigate to Studio > Widgets and click New Widget.

  2. Choose a Template

    Start from a blank widget or choose a template:

    • Card Widget - Basic card layout
    • Form Widget - Input form with validation
    • List Widget - Dynamic list display
    • Dashboard Widget - Stats and metrics display
  3. Design Your Widget

    Use the visual canvas to drag and drop components.

  4. Add Customization Options

    Define which properties users can customize.

  5. Publish Your Widget

    Version and publish for use across your apps.


The main design area where you arrange components visually.

  • Drag & Drop - Add components from the left panel
  • Select - Click to select and edit components
  • Multi-select - Shift+click for multiple components
  • Resize - Drag handles to resize
  • Reorder - Drag in the layer tree

Browse available components organized by category:

  • Layout - Row, Column, Grid, Stack
  • Display - Text, Image, Icon, Divider
  • Interactive - Button, TextField, Select
  • Container - Card, Modal, Tabs

Edit the selected component’s properties:

  • Content - Text, images, data bindings
  • Style - Tailwind classes, custom styles
  • Actions - Click handlers, form submissions
  • Responsive - Breakpoint-specific overrides

Manage the widget’s data model:

  • Add Data - Define data entries
  • Bind Data - Connect components to data paths
  • Mock Data - Preview with sample data

Let’s build a user profile card widget:

  1. Add a Card Container

    Drag a Card component onto the canvas.

  2. Add Layout

    Inside the card, add a Row for horizontal layout.

  3. Add Avatar

    Add an Image component for the avatar:

    Binding: /user/avatar
    Fallback: /default-avatar.png
    Style: w-16 h-16 rounded-full
  4. Add User Info

    Add a Column next to the image:

    • Text for name: { path: "/user/name" }
    • Text for role: { path: "/user/role" }
  5. Add Customization

    Go to Customization tab and add:

    • showRole (boolean) - Toggle role visibility
    • avatarSize (select) - sm, md, lg

Customization options let users configure your widget without editing its structure.

TypeDescriptionExample
stringText inputTitle, label
numberNumeric inputCount, size
booleanToggle switchShow/hide features
selectDropdownSize options, variants
colorColor pickerTheme colors
imageImage uploadCustom images
dataData pathDynamic content source
{
"customization": [
{
"id": "title",
"label": "Widget Title",
"type": "string",
"defaultValue": "My Widget"
},
{
"id": "variant",
"label": "Style Variant",
"type": "select",
"options": [
{ "value": "default", "label": "Default" },
{ "value": "compact", "label": "Compact" }
],
"defaultValue": "default"
},
{
"id": "showFooter",
"label": "Show Footer",
"type": "boolean",
"defaultValue": true
}
]
}

Reference customization options using the $options prefix:

{
"type": "Text",
"props": {
"content": { "path": "$options/title" }
}
}

Conditional rendering based on options:

{
"type": "Column",
"condition": { "path": "$options/showFooter" },
"children": [...]
}

Each widget has its own data model scoped to the widget instance:

/title - Widget title
/items - List of items
/items/0/name - First item's name
/user/avatar - User avatar URL

Use BoundValue objects to bind component props to data:

{
"type": "Text",
"props": {
"content": { "path": "/title" }
}
}

Widgets can receive data from parent contexts:

{
"type": "WidgetInstance",
"props": {
"widgetId": "user-card",
"data": {
"user": { "path": "/currentUser" }
}
}
}

Use Tailwind classes for styling:

{
"style": {
"className": "p-6 bg-white dark:bg-gray-800 rounded-xl shadow-lg hover:shadow-xl transition-all"
}
}

Add responsive breakpoints:

{
"style": {
"className": "p-4 md:p-6 lg:p-8 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"
}
}

Support dark mode with dark: prefix:

{
"style": {
"className": "bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100"
}
}

Widgets support semantic versioning (major.minor.patch):

  • Major (1.0.0 → 2.0.0): Breaking changes
  • Minor (1.0.0 → 1.1.0): New features, backward compatible
  • Patch (1.0.0 → 1.0.1): Bug fixes
  1. Make your changes in the builder
  2. Click Publish in the toolbar
  3. Select version increment type
  4. Add release notes
  5. Confirm publish

  • Keep widgets focused - One purpose per widget
  • Use semantic structure - Proper heading hierarchy
  • Support dark mode - Test both themes
  • Plan for responsiveness - Test all breakpoints
  • Minimize nesting - Flatten component hierarchy
  • Use lazy loading - For images and heavy content
  • Optimize data - Only bind necessary data
  • Use semantic components - Buttons, headings, labels
  • Add alt text - For all images
  • Support keyboard - All interactive elements
  • Test with screen readers - Verify announcements

Use FlowPilot to generate or modify widgets with AI:

  1. Select a widget or component
  2. Click Edit with FlowPilot in the toolbar
  3. Describe your changes:
    • “Add a loading state to this button”
    • “Make this card responsive with 2 columns on mobile”
    • “Add hover animations to all cards”