Variables

Variables are the key to creating dynamic, data-driven interfaces with UI Builder. Instead of hardcoding static values into your components, variables allow you to bind component properties to dynamic data that can change at runtime.

This transforms static designs into powerful applications with:

  • Personalized content that adapts to user data
  • Reusable templates that work across different contexts
  • Multi-tenant applications with customized branding per client
  • A/B testing and feature flags through boolean variables
Live Variables Example

Variable Types

UI Builder supports three typed variables:

tsx
1interface Variable { 2 id: string; // Unique identifier 3 name: string; // Display name (becomes property name in generated code) 4 type: 'string' | 'number' | 'boolean'; 5 defaultValue: string | number | boolean; // Must match the type 6} 7 8// Examples: 9const stringVar: Variable = { 10 id: 'page-title', 11 name: 'pageTitle', 12 type: 'string', 13 defaultValue: 'Welcome to UI Builder' 14}; 15 16const numberVar: Variable = { 17 id: 'user-age', 18 name: 'userAge', 19 type: 'number', 20 defaultValue: 25 21}; 22 23const booleanVar: Variable = { 24 id: 'is-loading', 25 name: 'isLoading', 26 type: 'boolean', 27 defaultValue: false 28};

๐Ÿ’ก See it in action: The demo above shows all three types with real-time variable binding and runtime value overrides.

Creating Variables

Via Initial Variables Prop

Set up variables when initializing the UIBuilder:

tsx
1import UIBuilder from '@/components/ui/ui-builder'; 2import { Variable } from '@/components/ui/ui-builder/types'; 3 4const initialVariables: Variable[] = [ 5 { 6 id: 'welcome-msg', 7 name: 'welcomeMessage', 8 type: 'string', 9 defaultValue: 'Welcome to our site!' 10 }, 11 { 12 id: 'user-count', 13 name: 'userCount', 14 type: 'number', 15 defaultValue: 0 16 }, 17 { 18 id: 'show-banner', 19 name: 'showBanner', 20 type: 'boolean', 21 defaultValue: true 22 } 23]; 24 25function App() { 26 return ( 27 <UIBuilder 28 componentRegistry={myComponentRegistry} 29 initialVariables={initialVariables} 30 onVariablesChange={(variables) => { 31 // Persist variable definitions to your backend 32 console.log('Variables updated:', variables); 33 }} 34 /> 35 ); 36}

Via the Data Panel

Users can create variables directly in the editor:

  1. Navigate to the "Data" tab in the left panel
  2. Click "Add Variable" to create a new variable
  3. Choose variable type (string, number, boolean)
  4. Set name and default value
  5. Variable is immediately available for binding in the props panel

Using Variables

Variables can be bound to component properties in two ways:

Manual Binding

Users can bind variables to component properties in the props panel by clicking the link icon next to any field.

Automatic Binding

Components can be configured to automatically bind to specific variables when added:

tsx
1const componentRegistry = { 2 UserProfile: { 3 component: UserProfile, 4 schema: z.object({ 5 userId: z.string(), 6 displayName: z.string(), 7 }), 8 from: '@/components/ui/user-profile', 9 // Automatically bind user data when component is added 10 defaultVariableBindings: [ 11 { 12 propName: 'userId', 13 variableId: 'current-user-id', 14 immutable: true // Cannot be unbound in UI 15 }, 16 { 17 propName: 'displayName', 18 variableId: 'current-user-name', 19 immutable: false // Can be changed by users 20 } 21 ] 22 } 23};

Immutable bindings prevent users from unbinding critical variables for system data, branding consistency, and template integrity.

๐Ÿ’ก Learn more: See Variable Binding for detailed binding mechanics and Data Binding for connecting to external data sources.

Variable Management

Controlling Variable Editing

Control whether users can edit variables in the UI:

tsx
1<UIBuilder 2 allowVariableEditing={false} // Hides add/edit/delete buttons 3 initialVariables={systemVariables} 4 componentRegistry={myComponentRegistry} 5/>

When allowVariableEditing is false:

  • Variables panel becomes read-only
  • "Add Variable" button is hidden
  • Edit/delete buttons on individual variables are hidden
  • Variable values can still be overridden at runtime during rendering

Variable Change Handling

Respond to variable definition changes in the editor:

tsx
1function App() { 2 const handleVariablesChange = (variables: Variable[]) => { 3 // Persist variable definitions to backend 4 fetch('/api/variables', { 5 method: 'POST', 6 body: JSON.stringify(variables) 7 }); 8 }; 9 10 return ( 11 <UIBuilder 12 componentRegistry={myComponentRegistry} 13 onVariablesChange={handleVariablesChange} 14 /> 15 ); 16}

Common Use Cases

Personalization

tsx
1// Variables for user-specific content 2const userVariables: Variable[] = [ 3 { id: 'user-name', name: 'userName', type: 'string', defaultValue: 'User' }, 4 { id: 'user-avatar', name: 'userAvatar', type: 'string', defaultValue: '/default-avatar.png' }, 5 { id: 'is-premium', name: 'isPremiumUser', type: 'boolean', defaultValue: false } 6];

Feature Flags

tsx
1// Variables for conditional features 2const featureFlags: Variable[] = [ 3 { id: 'show-beta-feature', name: 'showBetaFeature', type: 'boolean', defaultValue: false }, 4 { id: 'enable-dark-mode', name: 'enableDarkMode', type: 'boolean', defaultValue: true } 5];

Multi-tenant Branding

tsx
1// Variables for client-specific branding 2const brandingVariables: Variable[] = [ 3 { id: 'company-name', name: 'companyName', type: 'string', defaultValue: 'Acme Corp' }, 4 { id: 'primary-color', name: 'primaryColor', type: 'string', defaultValue: '#3b82f6' }, 5 { id: 'logo-url', name: 'logoUrl', type: 'string', defaultValue: '/default-logo.png' } 6];

Best Practices

  • Use descriptive names for variables (e.g., userName not u)
  • Choose appropriate types for your data (string for text, number for counts, boolean for flags)
  • Set meaningful default values for better preview experience in the editor
  • Use immutable bindings for system-critical data that shouldn't be unbound
  • Group related variables with consistent naming patterns
  • Keep variable names simple - they become property names in generated code
  • Separate variable definitions from values - define structure in the editor, inject data at runtime

Variable Workflow Summary

  1. Define Variables: Create variable definitions in the editor or via initialVariables
  2. Bind to Components: Link component properties to variables in the props panel
  3. Save Structure: Store the page structure and variable definitions (via onChange and onVariablesChange)
  4. Render with Data: Use LayerRenderer with variableValues to inject real data at runtime

This workflow enables the separation of content structure from actual data, making your UI Builder pages truly dynamic and reusable.

๐Ÿ“š Next Steps: Learn about Variable Binding for detailed binding mechanics, Data Binding for external data integration, and Rendering Pages for runtime usage.