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
Variable Types
UI Builder supports three typed variables:
tsx1interface 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:
tsx1import 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:
- Navigate to the "Data" tab in the left panel
- Click "Add Variable" to create a new variable
- Choose variable type (string, number, boolean)
- Set name and default value
- 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:
tsx1const 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:
tsx1<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:
tsx1function 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
tsx1// 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
tsx1// 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
tsx1// 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
notu
) - 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
- Define Variables: Create variable definitions in the editor or via
initialVariables
- Bind to Components: Link component properties to variables in the props panel
- Save Structure: Store the page structure and variable definitions (via
onChange
andonVariablesChange
) - Render with Data: Use
LayerRenderer
withvariableValues
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.