Get up and running with UI Builder in minutes. This guide covers installation, basic setup, and your first working editor.
If you are using shadcn/ui in your project, install the component directly from the registry:
bash1npx shadcn@latest add https://raw.githubusercontent.com/olliethedev/ui-builder/main/registry/block-registry.json
Or start a new Next.js project with UI Builder:
bash1npx shadcn@latest init https://raw.githubusercontent.com/olliethedev/ui-builder/main/registry/block-registry.json --base-color zinc
Install the full shadcn component library with 54 pre-configured components and 124 block templates:
bash1npx shadcn@latest add https://raw.githubusercontent.com/olliethedev/ui-builder/main/registry/shadcn-components-registry.json
See Shadcn Registry for details on using these components and blocks.
Note: You need to use style variables to have page theming working correctly.
If you encounter peer dependency warnings during installation (common with React 19 projects), create a .npmrc file in your project root:
bash1echo "legacy-peer-deps=true" > .npmrc
Then re-run the installation command.
The minimal setup requires just a component registry:
tsx1import UIBuilder from "@/components/ui/ui-builder"; 2import { primitiveComponentDefinitions } from "@/lib/ui-builder/registry/primitive-component-definitions"; 3import { complexComponentDefinitions } from "@/lib/ui-builder/registry/complex-component-definitions"; 4 5const componentRegistry = { 6 ...primitiveComponentDefinitions, // div, span, img, etc. 7 ...complexComponentDefinitions, // Button, Badge, Card, etc. 8}; 9 10export function App() { 11 return ( 12 <UIBuilder componentRegistry={componentRegistry} /> 13 ); 14}
This gives you a full visual editor with pre-built shadcn/ui components.
For real applications, you'll want to control the initial state and persist changes:
tsx1import UIBuilder from "@/components/ui/ui-builder"; 2import { ComponentLayer, Variable } from "@/components/ui/ui-builder/types"; 3 4// Initial page structure 5const initialLayers: ComponentLayer[] = [ 6 { 7 id: "welcome-page", 8 type: "div", 9 name: "Welcome Page", 10 props: { 11 className: "p-8 min-h-screen flex flex-col gap-6", 12 }, 13 children: [ 14 { 15 id: "title", 16 type: "h1", 17 name: "Page Title", 18 props: { 19 className: "text-4xl font-bold text-center", 20 }, 21 children: "Welcome to UI Builder!", 22 }, 23 { 24 id: "cta-button", 25 type: "Button", 26 name: "CTA Button", 27 props: { 28 variant: "default", 29 className: "mx-auto w-fit", 30 }, 31 children: [{ 32 id: "button-text", 33 type: "span", 34 name: "Button Text", 35 props: {}, 36 children: "Get Started", 37 }], 38 }, 39 ], 40 }, 41]; 42 43// Variables for dynamic content 44const initialVariables: Variable[] = [ 45 { 46 id: "welcome-msg", 47 name: "welcomeMessage", 48 type: "string", 49 defaultValue: "Welcome to UI Builder!" 50 } 51]; 52 53export function AppWithState() { 54 const handleLayersChange = (updatedLayers: ComponentLayer[]) => { 55 // Save to database, localStorage, etc. 56 console.log("Layers updated:", updatedLayers); 57 }; 58 59 const handleVariablesChange = (updatedVariables: Variable[]) => { 60 // Save to database, localStorage, etc. 61 console.log("Variables updated:", updatedVariables); 62 }; 63 64 return ( 65 <UIBuilder 66 componentRegistry={componentRegistry} 67 initialLayers={initialLayers} 68 onChange={handleLayersChange} 69 initialVariables={initialVariables} 70 onVariablesChange={handleVariablesChange} 71 /> 72 ); 73}
componentRegistry - Maps component names to their definitions (see Components Intro)initialLayers - Set initial page structure (e.g., from database)onChange - Callback when pages change (for persistence)initialVariables - Set initial variables for dynamic contentonVariablesChange - Callback when variables changeblocks - Block registry for the Blocks tab in add component popover (see Shadcn Registry)panelConfig - Customize editor panels (see Panel Configuration)persistLayerStore - Enable localStorage persistence (default: true)allowVariableEditing - Allow users to edit variables (default: true)allowPagesCreation - Allow users to create pages (default: true)allowPagesDeletion - Allow users to delete pages (default: true)These props provide simple customization of the default NavBar without replacing it entirely:
navLeftChildren - Content to render on the left side of the NavBarnavRightChildren - Content to render on the right side of the NavBarshowExport - Whether to show the Export button (default: true)Note: These props are only available when using the default NavBar. If you provide a custom navBar in panelConfig, these props are not available.
Note: Only componentRegistry is required. All other props are optional and have sensible defaults.
To display pages in production without the editor interface, use LayerRenderer (client) or ServerLayerRenderer (SSR/RSC):
tsx1import LayerRenderer from "@/components/ui/ui-builder/layer-renderer"; 2 3// Basic rendering (client component) 4export function MyPage({ page }) { 5 return ( 6 <LayerRenderer 7 page={page} 8 componentRegistry={componentRegistry} 9 /> 10 ); 11} 12 13// With variables for dynamic content 14export function DynamicPage({ page, userData }) { 15 const variableValues = { 16 "welcome-msg": `Welcome back, ${userData.name}!` 17 }; 18 19 return ( 20 <LayerRenderer 21 page={page} 22 componentRegistry={componentRegistry} 23 variables={variables} 24 variableValues={variableValues} 25 /> 26 ); 27}
For React Server Components or SSG, use ServerLayerRenderer:
tsx1import { ServerLayerRenderer } from "@/components/ui/ui-builder/server-layer-renderer"; 2 3// Server Component (no 'use client' needed) 4export default async function MyPage() { 5 const page = await fetchPageFromDB(); 6 return ( 7 <ServerLayerRenderer 8 page={page} 9 componentRegistry={componentRegistry} 10 /> 11 ); 12}
🎯 Try it: Check out the Renderer Demo, Variables Demo, and SSR Demo to see the renderers in action.
Now that you have UI Builder running, explore these key areas: