Skip to content

Commit b04c3fc

Browse files
committed
readme: updated
1 parent 43571ce commit b04c3fc

File tree

1 file changed

+55
-68
lines changed

1 file changed

+55
-68
lines changed

README.md

Lines changed: 55 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,30 @@
1-
# 🧩 Open-source Visual UI Builder — Build apps like Figma, Framer, and Webflow
1+
# 🧩 UI Builder — The Open-Source Visual Interface Builder for React
22

3-
UI Builder is a React component that lets you create and edit user interfaces through a fast, flexible no-code editor — powered by your own components or primitives.
3+
**UI Builder solves the fundamental problem of UI creation tools: they ignore your existing React component library and force you to rebuild from scratch.**
44

5-
- Visual no-code editor
6-
- Extensible with your components
7-
- Customizable user interface
8-
- Integrates with existing projects
9-
- Export pages as React code
10-
- Live preview of changes
11-
- Tailwind CSS support
5+
UI Builder is a shadcn/ui package that adds a Figma‑style editor to your own product, letting non‑developers compose pages, emails, dashboards, and white‑label views with the exact React components you already ship.
126

13-
Perfect for building landing pages, email templates, forms, admin dashboards, or giving your users no-code superpowers inside your product — without locking into closed platforms like Figma, Framer, Webflow, or Builder.io.
7+
Layouts are saved as plain JSON for easy versioning and can be rendered instantly allowing:
8+
9+
- your marketing team to update a landing page without waiting on engineering.
10+
- a customer to tweak a branded portal.
11+
- a product manager to modify email templates.
12+
- add a visual "head" to your headless CMS, connecting your content API with your component library.
1413

15-
🛠 Extend it. 🎨 Style it. 🚀 Own it.
1614

15+
How it unlocks novel product features:
1716

18-
See the [demo](https://uibuilder.app/) to get an idea of how it works.
17+
- Give users no‑code superpowers — add a full visual builder to your SaaS with one install.
18+
- Design with components you already ship — nothing new to build or maintain.
19+
- Store layouts as human‑readable JSON — render inside your product to ship changes immediately.
1920

20-
![UI Builder Demo](./public/demo.png)
21-
22-
## How it Works
23-
24-
UI Builder empowers you to visually construct and modify user interfaces by leveraging your own React components. Here's a breakdown of its core principles:
25-
26-
* **Component-Driven Foundation**: At its heart, UI Builder operates on your existing React components. You provide a `componentRegistry` detailing the components you want to make available in the editor. This registry includes the component itself, its Zod schema for props, its import path for code generation, and optional UI customizations for the editor.
27-
28-
* **Layer-Based Canvas**: The user interface is constructed as a tree of "layers." Each layer represents an instance of a component from your registry. Users can visually add, remove, reorder, and nest these layers on an interactive canvas, offering a direct manipulation experience. Any component type, like `div`, `main`, or custom containers, can serve as the root page layer.
29-
30-
* **Dynamic Props Editing**: Each component in the registry is defined with a Zod schema that outlines its props, their types, and default values. UI Builder utilizes this schema to automatically generate a properties panel (using [Auto-Form](https://github.com/vantezzen/autoform/tree/pure-shadcn)). This allows users to configure component instances in real-time, with changes immediately reflected on the canvas. Default values in the Zod schema are crucial for ensuring components render correctly when first added.
31-
32-
* **Centralized `componentRegistry`**: The `componentRegistry` prop passed to the `UIBuilder` component is central to its operation. It's a JavaScript object where you map a unique string identifier (e.g., "Button", "FancyComponent") to each component's detailed definition.
33-
34-
* **Flexible State Management**: By default, the editor's state (the arrangement and configuration of layers) is persisted in the browser's local storage for convenience across sessions. For more robust or backend-integrated solutions, you can provide `initialLayers` to seed the editor (e.g., from a database) and use the `onChange` callback to capture state changes and persist them as needed.
21+
See the [docs site](https://uibuilder.app/) for more information.
3522

36-
* **React Code Generation**: A key feature is the ability to export the visually designed page structure as clean, readable React code. This process uses the import paths (`from` property) specified in your component registry, ensuring the generated code correctly references your components.
23+
![UI Builder Demo](./public/demo.png)
3724

38-
* **Extensibility and Customization**: The system is designed for deep integration with your project:
39-
* Customize the properties form for each component using `fieldOverrides` to enhance the editing experience (e.g., custom labels, input types, or conditional visibility).
40-
* Provide custom React components via the `panelConfig` prop to provide custom components for the editor panels.
41-
* If you only need to display a UI Builder page without the editor, the `LayerRenderer` component can render it using the same `componentRegistry` and page data.
25+
---
4226

43-
This section aims to give a clearer picture of the UI Builder's architecture and how its different parts interact.
27+
# Quick Start
4428

4529
## Installation
4630

@@ -74,19 +58,18 @@ And that's it! You have a UI Builder that you can use to build your UI.
7458

7559
### Basic Example
7660

77-
To use the UI Builder, you need to provide a component registry and a form component for editing page-level properties.
61+
To use the UI Builder, you just need to provide a component registry.
7862

7963
```tsx
8064
import UIBuilder from "@/components/ui/ui-builder";
8165
import { ComponentRegistry } from "@/components/ui/ui-builder/types";
8266
import { primitiveComponentDefinitions } from "@/lib/ui-builder/registry/primitive-component-definitions"; // Basic html primitives registry
8367
import { complexComponentDefinitions } from "@/lib/ui-builder/registry/complex-component-definitions"; // Sample shadcn/ui components registry
8468

85-
// Combine or define your component registry
69+
// Define your component registry
8670
const myComponentRegistry: ComponentRegistry = {
8771
...primitiveComponentDefinitions,
8872
...complexComponentDefinitions,
89-
// ...add your custom components here
9073
};
9174

9275
export function App() {
@@ -98,8 +81,6 @@ export function App() {
9881
}
9982
```
10083

101-
By default the state of the UI is stored in the browser's local storage, so it will persist across sessions.
102-
10384
### Example with initial state and onChange callback
10485

10586
You can initialize the UI with initial layers from a database and use the onChange callback to persist the state to a database.
@@ -108,14 +89,8 @@ You can initialize the UI with initial layers from a database and use the onChan
10889
import React from "react";
10990
import UIBuilder from "@/components/ui/ui-builder";
11091
import { ComponentLayer, ComponentRegistry } from "@/components/ui/ui-builder/types";
111-
import { primitiveComponentDefinitions } from "@/lib/ui-builder/registry/primitive-component-definitions";
112-
import { complexComponentDefinitions } from "@/lib/ui-builder/registry/complex-component-definitions";
113-
114-
const myComponentRegistry: ComponentRegistry = {
115-
...primitiveComponentDefinitions,
116-
...complexComponentDefinitions
117-
};
11892

93+
const myComponentRegistry: ComponentRegistry = {...}; // Your component registry
11994

12095
// Static initial layers or you can fetch from database
12196
const initialLayers: ComponentLayer[] = [
@@ -192,19 +167,16 @@ export default App;
192167
- `persistLayerStore`: Optional boolean (defaults to `true`). Determines whether the editor's state (layers and their configurations) is persisted in the browser's local storage across sessions. Set to `false` to disable local storage persistence, useful if you are managing state entirely through `initialLayers` and `onChange`.
193168

194169

170+
## Rendering from Serialized Layer Data
171+
195172
You can also render the page layer without editor functionality by using the LayerRenderer component:
196173

197174
```tsx
198175
import LayerRenderer from "@/components/ui/ui-builder/layer-renderer";
199176
import { ComponentLayer } from "@/components/ui/ui-builder/types";
200177
import { ComponentRegistry } from "@/components/ui/ui-builder/types";
201-
import { primitiveComponentDefinitions } from "@/lib/ui-builder/registry/primitive-component-definitions"; // Example registry
202178

203-
// Component registry is needed for the renderer too
204-
const myComponentRegistry: ComponentRegistry = {
205-
...primitiveComponentDefinitions,
206-
// ...add your custom components here
207-
};
179+
const myComponentRegistry: ComponentRegistry = {...}; // Your component registry
208180

209181
const page: ComponentLayer = {...} // Fetch or define your page layer
210182

@@ -213,8 +185,6 @@ export function MyPage() {
213185
}
214186
```
215187

216-
`LayerRenderer` is useful when you want to render the finished page without any editor functionality. It also requires the `componentRegistry` to know how to render the components.
217-
218188
## Add your custom components to the registry
219189

220190
You add custom components by defining them in a `ComponentRegistry` object and passing that object to the `UIBuilder` component via the `componentRegistry` prop. The registry maps a unique component type name (string) to its definition.
@@ -223,16 +193,15 @@ Here is an example of how to define a custom component within the registry objec
223193

224194
```tsx
225195
import { z } from 'zod';
226-
import { FancyComponent } from '@/components/ui/fancy-component'; // Example custom component
196+
import { FancyComponent } from '@/components/ui/fancy-component'; // Example custom component with className, children, title, count, disabled, timestamp, mode props
227197
import { classNameFieldOverrides, childrenFieldOverrides } from "@/lib/ui-builder/registry/form-field-overrides";
228-
import { primitiveComponentDefinitions } from "@/lib/ui-builder/registry/primitive-component-definitions";
229198
import { ComponentRegistry } from "@/components/ui/ui-builder/types";
230199

231200
// Define your custom component's schema and configuration
232201
const fancyComponentDefinition = {
233202
// The React component itself
234203
component: FancyComponent,
235-
// The Zod schema defining the component's props
204+
// The Zod schema defining the component's props. This will be used to generate the properties form in the editor
236205
schema: z.object({
237206
className: z.string().optional(),
238207
children: z.any().optional(), // Use z.any() for children prop and provide custom handling in fieldOverrides
@@ -251,17 +220,15 @@ const fancyComponentDefinition = {
251220
from: "@/components/ui/fancy-component",
252221
// Customizations for the properties auto-form
253222
fieldOverrides: {
254-
className: (layer) => classNameFieldOverrides(layer), // Handle className selection with a custom component
255-
children: (layer) => childrenFieldOverrides(layer), // Handle children selection with a custom component
256-
// You can add overrides for other fields here
223+
className: (layer) => classNameFieldOverrides(layer), // Handle className selection with a custom component that is not a default auto-form component
224+
children: (layer) => childrenFieldOverrides(layer), // Handle children selection with a custom component that is not a default auto-form component
225+
// You can add your own component overrides for other fields here
257226
}
258227
};
259228

260-
// Create the full registry, potentially combining with existing definitions
229+
// Create the full registry, potentially combining with other component definitions
261230
export const myComponentRegistry: ComponentRegistry = {
262-
...primitiveComponentDefinitions, // Include base components if needed
263-
FancyComponent: fancyComponentDefinition, // Add your custom component under a unique name
264-
// ... add other custom components
231+
FancyComponent: fancyComponentDefinition,
265232
};
266233

267234
// Then pass `myComponentRegistry` to the UIBuilder prop:
@@ -275,6 +242,7 @@ export const myComponentRegistry: ComponentRegistry = {
275242
- This schema powers the automatic generation of a properties form in the editor using [Auto-Form](https://github.com/vantezzen/autoform/tree/pure-shadcn).
276243
- Currently supported Zod types for auto-form generation include: `boolean`, `date`, `number`, `string`, `enum` (of supported types), `object` (with supported property types), and `array` (of objects with supported property types).
277244
- `from`: **Required**. The source import path for the component. This is used when generating React code.
245+
- `isFromDefaultExport`: Optional. If true, indicates the component should be imported as a default export when generating React code.
278246
- `fieldOverrides`: Optional. An object to customize the auto-generated form fields for the component's properties in the editor's sidebar.
279247
- The keys of this object correspond to the prop names defined in the Zod schema.
280248
- The values are typically functions that receive the current `layer` object and return configuration options for the `AutoForm` field. These options can control the field's label, input type (`fieldType`), visibility (`isHidden`), placeholder text, render logic, and more. See the AutoForm documentation for available options.
@@ -285,12 +253,11 @@ export const myComponentRegistry: ComponentRegistry = {
285253
* Implementing conditional logic (e.g., showing/hiding a field based on another prop's value).
286254
- The example uses `classNameFieldOverrides` and `childrenFieldOverrides` from `@/lib/ui-builder/registry/form-field-overrides` to provide standardized handling for common props like `className` (using a auto suggest text input) and `children` (using a custom component). You can create your own override functions or objects.
287255
- `defaultChildren`: Optional. Default children to use when a new instance of this component is added to the canvas. For example setting initial text on a span component.
288-
- `isFromDefaultExport`: Optional. If true, indicates the component should be imported as a default export when generating React code.
289256

290257

291258
### Customizing the Page Config Panel Tabs
292259

293-
You can customize the tabs in the left "Page Config" panel (by default, "Layers" and "Appearance") by providing a `pageConfigPanelTabsContent` property inside the `panelConfig` prop. This allows you to change the tab titles or provide custom content for each tab.
260+
You can customize the tabs in the left "Page Config" panel (by default, "Layers" and "Appearance") by providing a `pageConfigPanelTabsContent` property inside the `panelConfig` prop. This allows you to change the tab titles or provide custom content for each tab. For example, you might want to provide your own appearance tab if you not using tailwind or a custom subset of tailwind like in React-Email .
294261

295262
```tsx
296263
import UIBuilder, { defaultConfigTabsContent } from "@/components/ui/ui-builder";
@@ -311,9 +278,29 @@ const myTabsContent = {
311278
```
312279

313280
If you do not provide this, the default tabs ("Layers" and "Appearance") will be used.
281+
You can also override other panels in the `panelConfig` like `editorPanel`, `propsPanel`, and `navBar`.
314282

315283
---
316-
For more detailed documentation read the [docs](https://uibuilder.app/)
284+
285+
## How it Works
286+
287+
UI Builder empowers you to visually construct and modify user interfaces by leveraging your own React components. Here's a breakdown of its core principles:
288+
289+
* **Component-Driven Foundation**: At its heart, UI Builder operates on your existing React components. You provide a `componentRegistry` detailing the components you want to make available in the editor. This registry includes the component itself, its Zod schema for props, its import path for code generation, and optional UI customizations for the editor.
290+
291+
* **Layer-Based Canvas**: The user interface is constructed as a tree of "layers." Each layer represents an instance of a component from your registry. Users can visually add, remove, reorder, and nest these layers on an interactive canvas, offering a direct manipulation experience. Any component type, like `div`, `main`, or custom containers, can serve as the root page layer.
292+
293+
* **Dynamic Props Editing**: Each component in the registry is defined with a Zod schema that outlines its props, their types, and default values. UI Builder utilizes this schema to automatically generate a properties panel (using [Auto-Form](https://github.com/vantezzen/autoform/tree/pure-shadcn)). This allows users to configure component instances in real-time, with changes immediately reflected on the canvas.
294+
295+
* **Flexible State Management**: By default, the editor's state (the arrangement and configuration of layers) is persisted in the browser's local storage for convenience across sessions. For more robust or backend-integrated solutions, you can provide `initialLayers` to seed the editor (e.g., from a database) and use the `onChange` callback to capture state changes and persist them as needed.
296+
297+
* **React Code Generation**: A key feature is the ability to export the visually designed page structure as clean, readable React code. This process uses the import paths (`from` property) specified in your component registry, ensuring the generated code correctly references your components.
298+
299+
* **Extensibility and Customization**: The system is designed for deep integration with your project:
300+
* Customize the properties form for each component using `fieldOverrides` to enhance the editing experience (e.g., custom labels, input types, or conditional visibility).
301+
* Provide custom React components via the `panelConfig` prop to provide custom components for the editor panels.
302+
* If you only need to display a UI Builder page without the editor, the `LayerRenderer` component can render it using the same `componentRegistry` and serialized page data.
303+
317304
---
318305

319306

@@ -358,15 +345,15 @@ npm run test
358345

359346
## Roadmap
360347

361-
- [ ] Add user friendly styling component instead of directly using tailwind classes
348+
- [ ] Add user friendly styling component along with of directly using tailwind classes
362349
- [ ] Add tiptap editor for markdown content
363350
- [ ] Add global variables for component props
364351
- [ ] Add Blocks. Reusable component blocks that can be used in multiple pages
365352
- [ ] Move component schemas to separate shadcn registry to keep main registry light
366353
- [ ] Move prop form field components (overrides) to separate shadcn registry to keep main registry light
367354
- [ ] Add data sources to component layers (ex, getUser() binds prop user.name)
368355
- [ ] Add event handlers to component layers (onClick, onSubmit, etc)
369-
- [ ] React native support
356+
- [ ] React Native support
370357
- [ ] Update to React 19
371358
- [ ] Update to latest Shadcn/ui + Tailwind CSS v4
372359
- [ ] Update to new AutoForm when stable

0 commit comments

Comments
 (0)