Skip to content

Search is only available in production builds. Try building and previewing the site to test it out locally.

UI Builder Overview

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.


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.


This package contains shared building blocks used across all UI components.

  • Avoid duplication
  • Standardize UI behavior
  • Provide shared utilities
common/
├─ adapters/
├─ components/
│ └─ ui/
└─ libs/

Wrappers around external dependencies to avoid tight coupling.

Examples:

  • Lucide icon adapter
  • Next.js Link adapter (wrapper around next/navigation)

Purpose:

  • Keep UI components framework-safe
  • Allow swapping implementations later without refactoring components

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:

  • getImage
  • getLogo
  • getVideo
  • navigationTree

Purpose:

  • Centralize logic
  • Avoid re-implementing helpers inside components

This package defines TypeScript interfaces for UI components.

  • Enforce strict typing
  • Decouple UI from CMS data
  • Provide a contract between schema and component
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.


This package acts as the source of truth for component metadata.

  • Central registry for all components
  • Bridge between UI packages and XSite builder
  • Provide schemas and preview metadata
registry/
├─ data/
├─ schema/
├─ component-registry.ts
└─ global.json

Contains 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

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

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

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"
}
}
}

This package contains the actual UI components.

Each component is treated as a self-contained Next.js app.


ui/
└─ cta/
├─ cta1/
├─ cta2/
└─ ...

Each component variant lives in its own folder.


cta1/
├─ package.json
├─ node_modules
└─ src/
├─ data.ts
├─ meta.ts
├─ schema.json
├─ storybook/
└─ runtime/

Contains dummy data for the component.

Used for:

  • Storybook rendering
  • Preview modes
  • Local development

Defines component metadata.

Includes:

  • Preview image
  • Component type
  • Category
  • Tags

This metadata is later aggregated into global.json.


Component-level schema.

Defines:

  • Editable fields
  • Field types
  • Validation rules

This schema must match:

  • The interface definition
  • The runtime component props

Used to:

  • Render component previews
  • Test component states
  • Develop UI in isolation

Contains the actual production code.

runtime/
├─ component.tsx
└─ index.ts
  • The real UI implementation
  • Uses shared UI components from common
  • Receives typed props from interfaces
  • Imports the component
  • Imports the interface
  • Exports a clean runtime entry

  1. Schema defines editable structure
  2. Interface defines typed props
  3. UI Component renders data
  4. Registry exposes metadata
  5. XSite Builder consumes schema + registry
  6. Editor edits data safely
  7. Renderer maps data → component

No step overlaps responsibility.


  • Strict separation of concerns
  • Schema-driven editing
  • Component-level isolation
  • Versionable UI packages
  • Safe, predictable rendering