UI BuilderUI Builder
Core
  • Introduction
  • Quick Start
Component System
  • Components Intro
  • Shadcn Registry
  • Custom Components
  • Advanced Configuration
  • Panel Configuration
Data & Variables
  • Variables
  • Variable Binding
  • Function Registry
  • Editing Restrictions
Layout & Persistence
  • Layer Structure
  • State Management & Persistence
Rendering
  • Rendering Pages
  1. Rendering
  2. Rendering Pages
Rendering Pages

Render UI Builder pages in production using LayerRenderer or ServerLayerRenderer. Display your designed pages without the editor interface, with full support for dynamic content through variables.

Choose the right renderer:

  • LayerRenderer - Client-side rendering with React hooks (use in client components)
  • ServerLayerRenderer - SSR/SSG/RSC compatible (use in server components, no 'use client' needed)
Basic Rendering Demo
Variables Demo
SSR Demo (Server Component)
Loading...

Basic Usage

Use the LayerRenderer component to display UI Builder pages without the editor interface:

tsx
1import LayerRenderer from '@/components/ui/ui-builder/layer-renderer'; 2import { ComponentLayer, ComponentRegistry } from '@/components/ui/ui-builder/types'; 3 4// Your component registry (same as used in UIBuilder) 5const myComponentRegistry: ComponentRegistry = { 6 // Your component definitions... 7}; 8 9// Page data from UIBuilder or database 10const page: ComponentLayer = { 11 id: "welcome-page", 12 type: "div", 13 name: "Welcome Page", 14 props: { 15 className: "p-6 max-w-4xl mx-auto" 16 }, 17 children: [ 18 { 19 id: "title", 20 type: "h1", 21 name: "Title", 22 props: { 23 className: "text-3xl font-bold mb-4" 24 }, 25 children: "Welcome to My App" 26 }, 27 { 28 id: "description", 29 type: "p", 30 name: "Description", 31 props: { 32 className: "text-gray-600" 33 }, 34 children: "This page was built with UI Builder." 35 } 36 ] 37}; 38 39function MyRenderedPage() { 40 return ( 41 <LayerRenderer 42 page={page} 43 componentRegistry={myComponentRegistry} 44 /> 45 ); 46}

Rendering with Variables

Make your pages dynamic by binding component properties to variables:

tsx
1import LayerRenderer from '@/components/ui/ui-builder/layer-renderer'; 2import { Variable } from '@/components/ui/ui-builder/types'; 3 4// Define your variables 5const variables: Variable[] = [ 6 { 7 id: "userName", 8 name: "User Name", 9 type: "string", 10 defaultValue: "Guest" 11 }, 12 { 13 id: "userAge", 14 name: "User Age", 15 type: "number", 16 defaultValue: 25 17 }, 18 { 19 id: "showWelcomeMessage", 20 name: "Show Welcome Message", 21 type: "boolean", 22 defaultValue: true 23 } 24]; 25 26// Page with variable bindings (created in UIBuilder) 27const pageWithVariables: ComponentLayer = { 28 id: "user-profile", 29 type: "div", 30 props: { 31 className: "p-6 bg-white rounded-lg shadow" 32 }, 33 children: [ 34 { 35 id: "welcome-message", 36 type: "h2", 37 props: { 38 className: "text-2xl font-bold mb-2", 39 children: { __variableRef: "userName" } // Bound to userName variable 40 }, 41 children: [] 42 }, 43 { 44 id: "age-display", 45 type: "p", 46 props: { 47 className: "text-gray-600", 48 children: { __variableRef: "userAge" } // Bound to userAge variable 49 }, 50 children: [] 51 } 52 ] 53}; 54 55// Provide runtime values for variables 56const variableValues = { 57 userName: "Jane Smith", 58 userAge: 28, 59 showWelcomeMessage: true 60}; 61 62function DynamicUserProfile() { 63 return ( 64 <LayerRenderer 65 page={pageWithVariables} 66 componentRegistry={myComponentRegistry} 67 variables={variables} 68 variableValues={variableValues} 69 /> 70 ); 71}

Production Integration

Integrate with your data sources to create personalized experiences:

tsx
1function CustomerPage({ customerId }: { customerId: string }) { 2 const [pageData, setPageData] = useState<ComponentLayer | null>(null); 3 const [customerData, setCustomerData] = useState({}); 4 5 useEffect(() => { 6 async function loadData() { 7 // Load page structure from your CMS/database 8 const pageResponse = await fetch('/api/pages/customer-dashboard'); 9 const page = await pageResponse.json(); 10 11 // Load customer-specific data 12 const customerResponse = await fetch(`/api/customers/${customerId}`); 13 const customer = await customerResponse.json(); 14 15 setPageData(page); 16 setCustomerData(customer); 17 } 18 19 loadData(); 20 }, [customerId]); 21 22 if (!pageData) return <div>Loading...</div>; 23 24 return ( 25 <LayerRenderer 26 page={pageData} 27 componentRegistry={myComponentRegistry} 28 variables={variables} 29 variableValues={{ 30 customerName: customerData.name, 31 companyLogo: customerData.logoUrl, 32 brandColor: customerData.primaryColor, 33 // Inject real customer data into the template 34 }} 35 /> 36 ); 37}

Performance Optimization

Optimize rendering performance for production:

tsx
1// Memoize the renderer to prevent unnecessary re-renders 2const MemoizedRenderer = React.memo(LayerRenderer, (prevProps, nextProps) => { 3 return ( 4 prevProps.page === nextProps.page && 5 JSON.stringify(prevProps.variableValues) === JSON.stringify(nextProps.variableValues) 6 ); 7}); 8 9// Use in your component 10function OptimizedPage() { 11 return ( 12 <MemoizedRenderer 13 page={page} 14 componentRegistry={myComponentRegistry} 15 variables={variables} 16 variableValues={variableValues} 17 /> 18 ); 19}

Error Handling

Handle rendering errors gracefully in production:

tsx
1import { ErrorBoundary } from 'react-error-boundary'; 2 3function ErrorFallback({ error }: { error: Error }) { 4 return ( 5 <div className="p-4 bg-red-50 border border-red-200 rounded"> 6 <h2 className="text-lg font-semibold text-red-800">Page failed to load</h2> 7 <p className="text-red-600">{error.message}</p> 8 <button 9 onClick={() => window.location.reload()} 10 className="mt-2 px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700" 11 > 12 Reload Page 13 </button> 14 </div> 15 ); 16} 17 18function SafeRenderedPage() { 19 return ( 20 <ErrorBoundary FallbackComponent={ErrorFallback}> 21 <LayerRenderer 22 page={page} 23 componentRegistry={myComponentRegistry} 24 variables={variables} 25 variableValues={variableValues} 26 /> 27 </ErrorBoundary> 28 ); 29}

LayerRenderer Props

  • page (required): The ComponentLayer to render
  • componentRegistry (required): Registry mapping component types to their definitions
  • className: Optional CSS class for the root container
  • variables: Array of Variable definitions available for binding
  • variableValues: Object mapping variable IDs to runtime values (overrides defaults)
  • editorConfig: Internal editor configuration (rarely needed in production)

ServerLayerRenderer (SSR/RSC)

For server-side rendering, static generation, or React Server Components, use ServerLayerRenderer. It provides the same rendering output as LayerRenderer but without any client-side dependencies.

When to Use ServerLayerRenderer

  • React Server Components (RSC) - Works in Next.js App Router server components
  • Static Site Generation (SSG) - Generate pages at build time
  • Server-Side Rendering (SSR) - Render pages on each request
  • No JavaScript required - Pages render without client-side JS

Basic SSR Usage

tsx
1// app/my-page/page.tsx - This is a Server Component (no 'use client') 2import { ServerLayerRenderer } from '@/components/ui/ui-builder/server-layer-renderer'; 3import { ComponentLayer } from '@/components/ui/ui-builder/types'; 4 5// Fetch page data on the server 6async function getPageData(): Promise<ComponentLayer> { 7 const res = await fetch('https://api.example.com/pages/home'); 8 return res.json(); 9} 10 11export default async function MyPage() { 12 const page = await getPageData(); 13 14 return ( 15 <ServerLayerRenderer 16 page={page} 17 componentRegistry={myRegistry} 18 /> 19 ); 20}

SSR with Variables

tsx
1// app/user/[id]/page.tsx 2import { ServerLayerRenderer } from '@/components/ui/ui-builder/server-layer-renderer'; 3 4export default async function UserPage({ params }: { params: { id: string } }) { 5 // Fetch data on the server 6 const [page, user] = await Promise.all([ 7 fetchPageTemplate(), 8 fetchUser(params.id) 9 ]); 10 11 // Inject server-side data into variables 12 const variableValues = { 13 userName: user.name, 14 userEmail: user.email, 15 memberSince: user.createdAt 16 }; 17 18 return ( 19 <ServerLayerRenderer 20 page={page} 21 componentRegistry={myRegistry} 22 variables={variables} 23 variableValues={variableValues} 24 /> 25 ); 26}

ServerLayerRenderer Props

  • page (required): The ComponentLayer to render
  • componentRegistry (required): Registry mapping component types to their definitions
  • className: Optional CSS class for the root container
  • variables: Array of Variable definitions available for binding
  • variableValues: Object mapping variable IDs to runtime values

Key Differences from LayerRenderer

FeatureLayerRendererServerLayerRenderer
React hooksUses hooksNo hooks
'use client'RequiredNot required
SSR/SSG/RSCNoYes
Editor integrationYesNo
Error boundariesBuilt-inUse your own
SuspenseBuilt-inUse your own

Best Practices

  1. Use the same componentRegistry in both UIBuilder and LayerRenderer
  2. Validate variable values before passing to LayerRenderer to prevent runtime errors
  3. Handle loading states while fetching page data and variables
  4. Implement error boundaries to gracefully handle rendering failures
  5. Cache page data when possible for better performance
  6. Memoize expensive variable calculations to avoid unnecessary re-computations
  7. Test variable bindings thoroughly to ensure robustness across different data scenarios