UI Builder Overview
UI Builder Repository Structure
Section titled “UI Builder Repository Structure”The XSite UI Builder is not a traditional monorepo.
It is organized as a Turborepo-based repository.
This distinction is important because it affects how packages are built, cached, and shared.
What This Means
Section titled “What This Means”XSite uses Turborepo to manage multiple packages with:
- Incremental builds
- Task-level caching
- Parallel execution
- Clear dependency graphs
Each package is independently versionable and buildable, while still benefiting from shared tooling and caching.
UI-BUILDER-Docs
Section titled “UI-BUILDER-Docs”packages/common
Section titled “packages/common”This package contains shared building blocks used across all UI components.
Purpose
Section titled “Purpose”- Avoid duplication
- Standardize UI behavior
- Provide shared utilities
Structure
Section titled “Structure”common/├─ adapters/├─ components/│ └─ ui/└─ libs/adapters/
Section titled “adapters/”Wrappers around external dependencies to avoid tight coupling.
Examples:
- Lucide icon adapter
- Next.js
Linkadapter (wrapper aroundnext/navigation)
Purpose:
- Keep UI components framework-safe
- Allow swapping implementations later without refactoring components
components/ui/
Section titled “components/ui/”Contains shared ShadCN-based UI components.
Examples:
- Button
- Input
- Card
- Modal
These are:
- Used while building UI components
- Not page-level components
- Purely presentational building blocks
Shared utility functions.
Examples:
getImagegetLogogetVideonavigationTree
Purpose:
- Centralize logic
- Avoid re-implementing helpers inside components
packages/interfaces
Section titled “packages/interfaces”This package defines TypeScript interfaces for UI components.
Purpose
Section titled “Purpose”- Enforce strict typing
- Decouple UI from CMS data
- Provide a contract between schema and component
Structure
Section titled “Structure”interfaces/└─ components/ ├─ about.ts ├─ hero.ts ├─ cta.ts └─ ...Each file:
- Represents a component type
- Defines props expected by UI components
- Matches the component schema shape
These interfaces are imported by UI components at runtime.
packages/registry
Section titled “packages/registry”This package acts as the source of truth for component metadata.
Purpose
Section titled “Purpose”- Central registry for all components
- Bridge between UI packages and XSite builder
- Provide schemas and preview metadata
Structure
Section titled “Structure”registry/├─ data/├─ schema/├─ component-registry.ts└─ global.jsonContains dummy / default data for components.
Options:
- One shared file for all variants (
about.json) - Individual files (
about1.json,about2.json)
Used for:
- Storybook
- Previews
- Fallback rendering
schema/
Section titled “schema/”Contains JSON schema files for each component.
Purpose:
- Define editable fields
- Validate content
- Power the XSite editor UI
These schemas are later:
- Consumed by XSite
- Used to generate editing forms
- Enforced during content updates
component-registry.ts
Section titled “component-registry.ts”Central file that:
- Imports all UI components
- Exposes them in a structured way
- Enables dynamic loading and rendering
This file is critical for:
- Component discovery
- Runtime resolution
- Builder integration
global.json
Section titled “global.json”Auto-generated file.
Contains:
- All component metadata
- Key-value mapping of components
- Preview images
- Categories and tags
This file is regenerated by a script whenever:
- Component metadata changes
- New components are added
- Preview images are updated
XSite uses this file to:
- Render component lists
- Show previews in the UI Builder
{ "hero": { "hero1": { "name": "Hero 1", "type": "hero", "category": "marketing", "tags": ["landing", "banner", "header"], "previewImage": "/previews/hero/hero1.webp", "schema": "hero/hero1/schema.json", "data": "hero/hero1/data.json", "runtime": "@xsite/ui-hero1" }, "hero2": { "name": "Hero 2", "type": "hero", "category": "marketing", "tags": ["product", "cta"], "previewImage": "/previews/hero/hero2.webp", "schema": "hero/hero2/schema.json", "data": "hero/hero2/data.json", "runtime": "@xsite/ui-hero2" } },
"cta": { "cta1": { "name": "CTA 1", "type": "cta", "category": "conversion", "tags": ["button", "action"], "previewImage": "/previews/cta/cta1.webp", "schema": "cta/cta1/schema.json", "data": "cta/cta1/data.json", "runtime": "@xsite/ui-cta1" } },
"about": { "about1": { "name": "About Section 1", "type": "about", "category": "content", "tags": ["company", "info"], "previewImage": "/previews/about/about1.webp", "schema": "about/about1/schema.json", "data": "about/about1/data.json", "runtime": "@xsite/ui-about1" } }}packages/ui
Section titled “packages/ui”This package contains the actual UI components.
Each component is treated as a self-contained Next.js app.
Folder Structure
Section titled “Folder Structure”ui/└─ cta/ ├─ cta1/ ├─ cta2/ └─ ...Each component variant lives in its own folder.
Inside a Component (cta1)
Section titled “Inside a Component (cta1)”cta1/├─ package.json├─ node_modules└─ src/ ├─ data.ts ├─ meta.ts ├─ schema.json ├─ storybook/ └─ runtime/data.ts
Section titled “data.ts”Contains dummy data for the component.
Used for:
- Storybook rendering
- Preview modes
- Local development
meta.ts
Section titled “meta.ts”Defines component metadata.
Includes:
- Preview image
- Component type
- Category
- Tags
This metadata is later aggregated into global.json.
schema.json
Section titled “schema.json”Component-level schema.
Defines:
- Editable fields
- Field types
- Validation rules
This schema must match:
- The interface definition
- The runtime component props
storybook/
Section titled “storybook/”Used to:
- Render component previews
- Test component states
- Develop UI in isolation
runtime/
Section titled “runtime/”Contains the actual production code.
runtime/├─ component.tsx└─ index.tscomponent.tsx
Section titled “component.tsx”- The real UI implementation
- Uses shared UI components from
common - Receives typed props from interfaces
index.ts
Section titled “index.ts”- Imports the component
- Imports the interface
- Exports a clean runtime entry
How Everything Connects
Section titled “How Everything Connects”- Schema defines editable structure
- Interface defines typed props
- UI Component renders data
- Registry exposes metadata
- XSite Builder consumes schema + registry
- Editor edits data safely
- Renderer maps data → component
No step overlaps responsibility.
Key Design Principles
Section titled “Key Design Principles”- Strict separation of concerns
- Schema-driven editing
- Component-level isolation
- Versionable UI packages
- Safe, predictable rendering