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)Use the LayerRenderer component to display UI Builder pages without the editor interface:
tsx1import 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}
Make your pages dynamic by binding component properties to variables:
tsx1import 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}
Integrate with your data sources to create personalized experiences:
tsx1function 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}
Optimize rendering performance for production:
tsx1// 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}
Handle rendering errors gracefully in production:
tsx1import { 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}
page (required): The ComponentLayer to rendercomponentRegistry (required): Registry mapping component types to their definitionsclassName: Optional CSS class for the root containervariables: Array of Variable definitions available for bindingvariableValues: Object mapping variable IDs to runtime values (overrides defaults)editorConfig: Internal editor configuration (rarely needed in production)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.
tsx1// 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}
tsx1// 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}
page (required): The ComponentLayer to rendercomponentRegistry (required): Registry mapping component types to their definitionsclassName: Optional CSS class for the root containervariables: Array of Variable definitions available for bindingvariableValues: Object mapping variable IDs to runtime values| Feature | LayerRenderer | ServerLayerRenderer |
|---|---|---|
| React hooks | Uses hooks | No hooks |
| 'use client' | Required | Not required |
| SSR/SSG/RSC | No | Yes |
| Editor integration | Yes | No |
| Error boundaries | Built-in | Use your own |
| Suspense | Built-in | Use your own |
componentRegistry in both UIBuilder and LayerRenderer