A pnpm workspace containing reusable components distributed via Copy & Own model.
| Document | Description |
|---|---|
| QUICKSTART.md | Setup guide for MCP Server & CLI |
| docs/DOCS_INDEX.md | Complete documentation index |
| docs/ARCHITECTURE.md | System architecture diagrams |
| docs/CLI.md | CLI commands & agent reference |
| docs/DISTRIBUTION.md | Distribution methods + Amplify hosting |
| docs/TESTING.md | Playwright E2E testing guide |
| docs/PUBLISHING.md | npm publishing & release workflow |
| docs/WINDOWS.md | Windows development guide |
buildpad-ui/
βββ pnpm-workspace.yaml # Workspace configuration (packages/* + apps/*)
βββ package.json # Root scripts
βββ docs/ # Documentation
β βββ DOCS_INDEX.md # Documentation index
β βββ ARCHITECTURE.md # System architecture
β βββ CLI.md # CLI commands & agent reference
β βββ COMPONENT_MAP.md # Quick component lookup table
β βββ DESIGN_SYSTEM.md # Token-based theming architecture
β βββ DISTRIBUTION.md # Distribution guide
β βββ PUBLISHING.md # npm publishing & release workflow
β βββ TESTING.md # Playwright E2E testing guide
β βββ WINDOWS.md # Windows setup
βββ apps/ # Standalone applications
β βββ storybook-host/ # Next.js auth proxy & Storybook host (Amplify)
β βββ app/api/ # DaaS proxy routes (connect, disconnect, status, catch-all)
β βββ lib/cookie.ts # AES-256-GCM encrypted credential storage
β βββ public/storybook/ # Built Storybooks served at /storybook/*
βββ tests/ # Playwright E2E tests
β βββ auth.setup.ts # Authentication setup
β βββ ui-form/ # VForm component tests
β βββ ui-table/ # VTable component tests
βββ packages/ # Component library (source of truth)
βββ registry.json # Component registry schema
βββ cli/ # CLI tool for developers (@buildpad/cli)
βββ mcp-server/ # MCP server for AI agents (@buildpad/mcp)
βββ ui-interfaces/ # Field interface components (Storybook port 6005)
βββ ui-form/ # VForm dynamic form component (Storybook port 6006)
βββ ui-table/ # VTable dynamic table component (Storybook port 6007)
βββ ui-collections/ # Collection Form & List (Storybook port 6008)
βββ types/ # Shared TypeScript types
βββ services/ # Shared service classes
βββ hooks/ # Shared React hooks
βββ utils/ # Utility functions (field mapper, etc.)
- Node.js >= 18.0.0
- pnpm >= 9.0.0
# Clone both repositories into this workspace
# (or use git submodules)
# Install all dependencies
pnpm install
# Build all packages
pnpm build# Run Storybook for UI component development
pnpm --filter @buildpad/ui-interfaces storybook
# Build shared packages first
pnpm --filter './packages/**' buildShared TypeScript type definitions following DaaS conventions.
Key Types:
PrimaryKey,AnyItem,Filter,Query- Core data typesField,FieldMeta,Collection,CollectionMeta- Schema typesDaaSFile,FileUpload,Folder- File system typesM2MRelationInfo,M2ORelationInfo,O2MRelationInfo- Relation typesPermission,Accountability- Access control types
Usage:
import type { Field, Collection, Query, PrimaryKey } from "@buildpad/types";
import {
getFileCategory,
formatFileSize,
getAssetUrl,
} from "@buildpad/types";Service classes for DaaS API configuration and authentication.
Available Services:
FieldsService- Read field definitionsCollectionsService- Read collection metadataPermissionsService- Field-level permissions
API Request Utilities:
apiRequest- Make API requests (supports both proxy and direct DaaS modes)buildApiUrl- Build URL for API requests respecting DaaS configurationgetApiHeaders- Get headers with auth token when in direct mode
DaaS Context (for Storybook/Testing):
DaaSProvider- React provider for direct DaaS API access with authentication stateuseDaaSContext- Hook to access DaaS config, user info, and auth helperssetGlobalDaaSConfig- Set global config for non-React contexts
Authentication Module (@buildpad/services/auth):
configureAuth/createAuthenticatedClient/getCurrentUser- Session managementenforcePermission/getAccessibleFields/filterFields- Permission enforcementapplyFilterToQuery/resolveFilterDynamicValues- Filter-to-query conversion- Cookie-based sessions for browser requests (automatic)
- Static tokens for programmatic access (DaaS-style)
- JWT Bearer tokens for API clients with Supabase Auth
Usage:
import { FieldsService } from "@buildpad/services";
const fieldsService = new FieldsService();
const fields = await fieldsService.readAll("products");Direct DaaS Mode (Storybook/Testing):
import { DaaSProvider } from "@buildpad/services";
// Wrap components to enable direct DaaS API access
<DaaSProvider
config={{
url: "https://xxx.buildpad-daas.xtremax.com",
token: "your-token",
}}
>
<VForm collection="articles" />
</DaaSProvider>;React hooks for managing authentication, permissions, DaaS relationships, selection, presets, and workflows.
Authentication Hooks (DaaS-compatible):
useAuth- Authentication state (user, isAdmin, isAuthenticated) and methods (refresh, logout, checkPermission)usePermissions- Field-level and action-level permission checking (canPerform, getAccessibleFields, isFieldAccessible)useDaaSContext/DaaSProvider- DaaS configuration context for direct API access
Relation Hooks:
useRelationM2M/useRelationM2MItems- Many-to-Many relationshipsuseRelationM2O/useRelationM2OItem- Many-to-One relationshipsuseRelationO2M/useRelationO2MItems- One-to-Many relationshipsuseRelationM2A/useRelationM2AItems- Many-to-Any (polymorphic) relationshipsuseFiles- File upload and management
Selection & Preset Hooks:
useSelection- Item selection managementusePreset- Collection presets (filters, search, layout)
Navigation & State Hooks:
useEditsGuard/useHasEdits- Unsaved changes navigation guarduseClipboard- Clipboard operations with notificationsuseLocalStorage- Persistent localStorage state
Workflow & Versioning Hooks:
useVersions- Content version management (create, save, delete versions)useWorkflowAssignment- Check if collection has workflow assignmentuseWorkflowVersioning- Workflow + versioning integration (edit modes, state tracking)
Usage:
import { useAuth, usePermissions, useRelationM2M } from "@buildpad/hooks";
// Authentication
function UserProfile() {
const { user, isAdmin, isAuthenticated, loading } = useAuth();
if (!isAuthenticated) return <LoginButton />;
return <div>Welcome, {user.first_name}!</div>;
}
// Permissions
function ArticleEditor({ articleId }) {
const { canPerform, getAccessibleFields } = usePermissions({
collections: ["articles"],
});
if (!canPerform("articles", "update")) return <Alert>No edit access</Alert>;
const fields = getAccessibleFields("articles", "update");
// ...
}
// Relations
function ProductTags({ productId }: { productId: string }) {
const { relationInfo, loading } = useRelationM2M("products", "tags");
// Manage M2M relationships...
}Utility functions for field interface mapping and validation. The field interface mapper is the core logic that VForm uses to determine which UI component to render for each field type.
Key Functions:
getFieldInterface- Map field types to UI interface components (40+ types)isFieldReadOnly- Determine read-only status based on contextgetFieldValidation- Extract validation rules from field schemaformatFieldValue- Format values for displayisPresentationField- Check for presentation-only fields (divider, notice)
Usage:
import { getFieldInterface, isFieldReadOnly } from "@buildpad/utils";
const interfaceConfig = getFieldInterface(field);
// Returns: { type: 'input', props: { type: 'string' } }
// or: { type: 'select-dropdown', props: { choices: [...] } }
// or: { type: 'list-m2m', props: { relationInfo: {...} } }
const readOnly = isFieldReadOnly(field, "edit");
// Returns: true for auto-increment PKs, UUID PKs, etc.CLI Installation:
When you add components via CLI, the field-interface-mapper is automatically included in lib/buildpad/ allowing VForm and CollectionForm to correctly render all 40+ interface types.
DaaS-compatible field interface components built with Mantine v8.
Core Components:
| Component | Description |
|---|---|
Boolean |
Switch toggle |
Toggle |
Enhanced toggle with icons and state labels |
DateTime |
Date/time picker |
Input |
Single-line text input |
Textarea |
Multi-line text input |
InputCode |
Monospace code editor with line numbers |
Selection Components:
| Component | Description |
|---|---|
SelectDropdown |
Dropdown select with search |
SelectRadio |
Radio button selection |
SelectMultipleCheckbox |
Checkbox group with "other" option |
SelectMultipleCheckboxTree |
Tree-based hierarchical multi-select |
SelectMultipleDropdown |
Dropdown-based multi-select with search |
SelectIcon |
Icon picker with categorized Tabler icons |
Tags |
Tag input with presets and custom tags |
AutocompleteAPI |
External API-backed autocomplete |
CollectionItemDropdown |
Collection item selector dropdown |
Layout Components:
| Component | Description |
|---|---|
Divider |
Horizontal/vertical divider with title support |
Notice |
Alert/notice component (info, success, warning, danger) |
Slider |
Range slider with numeric type support |
GroupDetail |
Collapsible form section |
Rich Text Components: (require additional dependencies)
| Component | Description |
|---|---|
RichTextHtml |
WYSIWYG HTML editor (requires @tiptap packages) |
RichTextMarkdown |
Markdown editor with live preview |
InputBlockEditor |
Block-based editor using EditorJS (SSR-safe with dynamic import) |
InputCode |
Monospace code editor with syntax highlighting |
Media Components:
| Component | Description |
|---|---|
File |
Single file with DaaS Files API integration |
FileImage |
Image file picker with preview, lightbox, and crop |
Files |
Multiple files interface (M2M relationship with junction table support) |
Upload |
Low-level drag-and-drop file upload zone |
Color |
Color picker with RGB/HSL support, presets, opacity |
Map |
Interactive map placeholder for coordinates |
MapWithRealMap |
Full MapLibre GL JS map with drawing tools |
Relational Components:
| Component | Description |
|---|---|
ListM2M |
Many-to-Many list with hooks integration |
ListM2O |
Many-to-One selector with hooks integration |
ListO2M |
One-to-Many list with hooks integration |
ListM2A |
Many-to-Any polymorphic list with hooks integration |
ListM2MInterface |
Many-to-Many (render-prop variant) |
ListM2OInterface |
Many-to-One (render-prop variant) |
ListO2MInterface |
One-to-Many (render-prop variant) |
Workflow Components:
| Component | Description |
|---|---|
WorkflowButton |
Workflow state button with transitions, policy-based commands, and revision comparison |
Usage:
import {
Boolean, DateTime, SelectDropdown, Color, Notice, Tags, WorkflowButton
} from '@buildpad/ui-interfaces';
// Basic components
<DateTime value={date} onChange={setDate} type="datetime" label="Pick a date" />
<Color value={color} onChange={setColor} label="Brand Color" opacity />
<Notice type="success" title="Saved">Your changes have been saved.</Notice>
<Tags value={tags} onChange={setTags} presets={['React', 'Vue', 'Angular']} />
// Workflow state management
<WorkflowButton
itemId="article-123"
collection="articles"
canCompare={true}
onChange={(value) => console.log('New state:', value)}
onTransition={() => console.log('Transition complete')}
/>Dynamic form component system inspired by DaaS v-form, with comprehensive Storybook documentation and built-in permission enforcement.
Components:
| Component | Description |
|---|---|
VForm |
Main dynamic form component that renders fields based on collection schema |
FormField |
Individual field wrapper with label, validation, and interface rendering |
FormFieldLabel |
Label component with required indicator and tooltip |
FormFieldInterface |
Dynamic interface component loader |
Features:
- π― Dynamic field rendering based on schema
- π 40+ interface types (input, textarea, boolean, datetime, select, etc.)
- π Permission enforcement - Filter fields based on user permissions (DaaS-compatible)
- β Validation error display with field-level messages
- π± Responsive grid layout (full, half, fill widths)
- π Change tracking and dirty state management
- π Field groups and hierarchical organization
- π Create vs Edit mode with proper state handling
- π Read-only and disabled field support
Storybook Stories:
- Basic Stories (
VForm.stories.tsx) - Mocked data examples covering all interface types, layouts, validation, and states - DaaS Playground (
VForm.daas.stories.tsx) - Connect to a real DaaS instance and test with actual collection schemas
Usage:
import { VForm } from "@buildpad/ui-form";
import { DaaSProvider } from "@buildpad/services";
// Basic usage
function MyForm() {
const [values, setValues] = useState({});
return (
<VForm
collection="articles"
modelValue={values}
onUpdate={setValues}
validationErrors={errors}
primaryKey="+" // '+' for create mode
/>
);
}
// With permission enforcement
function ProtectedForm() {
return (
<DaaSProvider
config={{ url: "https://xxx.buildpad-daas.xtremax.com", token: "xxx" }}
>
<VForm
collection="articles"
modelValue={values}
onUpdate={setValues}
enforcePermissions={true}
action="update" // 'create' | 'update' | 'read'
onPermissionsLoaded={(fields) => console.log("Accessible:", fields)}
/>
</DaaSProvider>
);
}Testing:
# Run Storybook for VForm development
pnpm storybook:form
# Run isolated component tests
pnpm test:storybook
# Run DaaS integration tests
pnpm test:e2eDynamic collection components for forms, tables, navigation, and layouts. Inspired by DaaS's content module.
Components:
| Component | Description |
|---|---|
CollectionForm |
CRUD form wrapper with data fetching - uses VForm for rendering all 40+ interface types |
CollectionList |
Dynamic table with pagination, search, selection, bulk actions |
ContentLayout |
Shell layout with sidebar navigation and main content area |
ContentNavigation |
Hierarchical sidebar navigation for collections with search and bookmarks |
FilterPanel |
Field-type-aware filter builder for collection queries |
SaveOptions |
Dropdown menu with save actions (save & stay, save & add new, etc.) |
Architecture:
- CollectionForm = Data layer (fetch fields, load/save items, CRUD operations)
- VForm = Presentation layer (renders fields with proper interfaces from @buildpad/ui-interfaces)
- ContentLayout + ContentNavigation = Complete content module shell (like DaaS)
- FilterPanel = Visual filter builder producing DaaS-compatible filter objects
When you install collection-form via CLI, VForm and all 32 dependent interface components are automatically included.
Storybook:
pnpm storybook:collections # Port 6008Usage:
import {
CollectionForm,
CollectionList,
ContentLayout,
ContentNavigation,
FilterPanel,
SaveOptions
} from '@buildpad/ui-collections';
// Complete content module
<ContentLayout
title="Products"
navigation={<ContentNavigation collections={collections} onNavigate={setCollection} />}
>
<CollectionList collection="products" filter={filter} />
</ContentLayout>
// Form with save options
<CollectionForm collection="products" id={id} />
<SaveOptions onSaveAndStay={handleSave} onSaveAndAddNew={handleSaveAndNew} />
// Filter builder
<FilterPanel fields={fields} value={filter} onChange={setFilter} />Dynamic table component inspired by DaaS v-table, built with Mantine v8 and @dnd-kit.
Components:
| Component | Description |
|---|---|
VTable |
Main dynamic table component |
TableHeader |
Header row with sorting, resize handles, select all |
TableRow |
Data row with selection, drag handle, custom cells |
Features:
- π Column sorting (ascending/descending toggle)
βοΈ Column resizing via drag handles- β Row selection (single/radio or multiple/checkbox)
- π Manual row sorting via drag-and-drop (@dnd-kit)
- β³ Loading/empty states with skeletons
- π Fixed/sticky header option
- π¨ Inline (bordered) styling option
- π― Custom cell rendering
- π§ Row actions slot
- β¨οΈ Keyboard navigation for clickable rows
- π Dark mode support
Usage:
import { VTable } from "@buildpad/ui-table";
<VTable
headers={[
{ text: "Name", value: "name", sortable: true, width: 200 },
{ text: "Email", value: "email", sortable: true, width: 250 },
{ text: "Status", value: "status", sortable: true, width: 100 },
]}
items={users}
itemKey="id"
showSelect="multiple"
showResize
sort={{ by: "name", desc: false }}
onSortChange={setSort}
onUpdate={setSelectedUsers}
/>;Storybook Stories:
- Basic Stories (
VTable.stories.tsx) - Mocked data examples covering all features (sorting, selection, resizing, drag-and-drop, etc.) - DaaS Playground (
VTable.daas.stories.tsx) - Connect to a real DaaS instance and test with actual collection data
Testing:
# Run Storybook for VTable development
pnpm storybook:table
# Run Playwright tests against VTable Storybook
SKIP_WEBSERVER=true STORYBOOK_TABLE_URL=http://localhost:6007 \
npx playwright test tests/ui-table --project=storybook-tableBuildpad includes two powerful distribution tools:
Expose Buildpad components to AI assistants like VS Code Copilot.
The MCP server is published on npm as @buildpad/mcp.
// Add to VS Code settings.json or .vscode/mcp.json:
{
"mcp": {
"servers": {
"buildpad": {
"command": "npx",
"args": ["@buildpad/mcp@latest"]
}
}
}
}# Use with Copilot:
# "Show me how to use the Input component from Buildpad"
# "Generate a CollectionForm for products"
# "Get RBAC pattern for own_items on articles collection"Available MCP Tools:
list_components- Discover all components by categoryget_component- Read source code and metadatalist_packages- List all available packages with exportsget_install_command- Get CLI install commandsget_copy_own_info- Explain the Copy & Own distribution modelcopy_component- Get full source for manual copygenerate_form/generate_interface- Code generationget_usage_example- Usage examples with local importsget_rbac_pattern- Generate RBAC setup sequences (own_items, role_hierarchy, public_read, multi_tenant, full_crud, read_only)
Copy components directly to your project (like shadcn/ui).
The CLI is published on npm as @buildpad/cli.
# Use in any project (no local build needed)
npx @buildpad/cli@latest init
npx @buildpad/cli@latest add input select-dropdown
npx @buildpad/cli@latest list
npx @buildpad/cli@latest add --category selection
npx @buildpad/cli@latest add --all
# Bootstrap entire project in one command (recommended for AI agents)
npx @buildpad/cli@latest bootstrapWhat bootstrap does:
- Creates
buildpad.jsonand project skeleton - Copies all 40+ UI components to
components/ui/ - Copies types, services, hooks to
lib/buildpad/ - Copies API proxy routes (fields, items, relations, files)
- Copies auth proxy routes (login, logout, user, callback) + login page
- Copies Supabase auth utilities and middleware
- Runs
pnpm installto resolve all dependencies - Validates the installation
Benefits:
- β Source code remains private
- β AI agents can discover and use components
- β Developers get full control over copied code
- β
Published on npm (
@buildpad/cli,@buildpad/mcp)
See QUICKSTART.md for detailed setup guide.
| Command | Description |
|---|---|
pnpm install |
Install all dependencies |
pnpm build |
Build all packages and apps |
pnpm build:mcp |
Build MCP server for AI agents |
pnpm build:cli |
Build CLI tool |
pnpm dev |
Run all apps in dev mode |
pnpm mcp:dev |
Run MCP server in watch mode |
pnpm cli |
Run CLI tool locally |
pnpm cli validate |
Validate Buildpad installation in a project |
pnpm storybook |
Run Storybook for ui-interfaces (port 6005) |
pnpm storybook:form |
Run VForm Storybook (port 6006) |
pnpm storybook:table |
Run VTable Storybook (port 6007) |
pnpm storybook:collections |
Run Collections Storybook (port 6008) |
pnpm build:storybook |
Build all 4 Storybooks to host app's public dir |
pnpm dev:host |
Start Storybook host app in dev mode (port 3000) |
pnpm build:host |
Build the Storybook host app for production |
pnpm start:host |
Start production Storybook host app |
pnpm lint |
Lint all projects |
pnpm clean |
Remove node_modules and build artifacts |
pnpm test:e2e |
Run Playwright E2E tests against DaaS |
pnpm test:storybook |
Run Playwright tests against VForm Storybook |
pnpm test:storybook:table |
Run Playwright tests against VTable Storybook |
All Storybooks use Storybook 10 with @storybook/nextjs-vite.
# Run individual Storybooks
pnpm storybook # ui-interfaces (port 6005)
pnpm storybook:form # VForm (port 6006)
pnpm storybook:table # VTable (port 6007)
pnpm storybook:collections # Collections (port 6008)
# Build all Storybooks for hosting
pnpm build:storybookThe DaaS Playground uses a Next.js host app (apps/storybook-host) as an authentication proxy, avoiding CORS issues:
# Terminal 1: Start the host app (DaaS auth proxy)
pnpm dev:host
# Terminal 2: Start Storybook
pnpm storybook:form- Open
http://localhost:3000and connect with your DaaS URL + static token - Navigate to DaaS Playground stories in any Storybook (VForm, VTable, CollectionForm, CollectionList)
- Select a collection and test with real fields and data
Credentials are stored in an AES-256-GCM encrypted httpOnly cookie. All /api/* requests from Storybook are proxied through the host app.
Buildpad uses a two-tier testing strategy for comprehensive validation:
# Start VForm Storybook and run Playwright tests
pnpm storybook:form # Start Storybook on port 6006
pnpm test:storybook # Run Playwright against StorybookAdvantages:
- β No Authentication Required - Test components with mocked data
- β Fast Feedback - Isolated component testing without backend dependencies
- β All Interface Types - Test any field configuration without database setup
- β DaaS Playground - Connect to real DaaS API and test with actual schemas
Test Files:
tests/ui-form/vform-storybook.spec.ts- VForm tests against Storybook storiestests/ui-table/vtable-storybook.spec.ts- VTable tests against Storybook stories (22 tests)packages/ui-form/src/VForm.stories.tsx- VForm basic stories with mocked datapackages/ui-form/src/VForm.daas.stories.tsx- VForm DaaS playground for real API testingpackages/ui-table/src/VTable.stories.tsx- VTable basic stories with mocked datapackages/ui-table/src/VTable.daas.stories.tsx- VTable DaaS playground for real API testing
# Run against hosted DaaS (requires auth)
pnpm test:e2e # Run all E2E tests
pnpm test:e2e:ui # Interactive Playwright UIAdvantages:
- β Real API - Actual Supabase backend integration
- β Authentication - Test with real users and roles
- β Permissions - Verify field-level access control
- β Full Workflow - End-to-end form submission and validation
Test Files:
tests/ui-form/vform-daas.spec.ts- Integration tests with DaaS apptests/ui-form/vform.spec.ts- Complete E2E workflow teststests/auth.setup.ts- Authentication setup for admin usertests/helpers/seed-test-data.ts- Test data seeding utilities
Playwright Configuration:
playwright.config.ts- Dual-mode setup (Storybook + DaaS)- Auto-starts Storybook for component tests
- Uses admin authentication for DaaS E2E tests
See docs/TESTING.md for complete testing guide and best practices.
- Add component to
packages/ui-interfaces/src/<component-name>/ - Export from
packages/ui-interfaces/src/index.ts - Update
packages/ui-interfaces/package.jsonexports if needed - Run
pnpm installto update workspace links
- Shared dependencies go in the relevant package's
package.json - Use
workspace:*protocol for internal packages - Peer dependencies for Mantine, React in shared packages
Buildpad integrates with the buildpad-copilot RAD (Rapid Application Development) platform for AI-assisted development.
# Clone the RAD platform boilerplate
git clone https://github.com/your-org/buildpad-copilot.git my-new-app
cd my-new-app
# The .vscode/mcp.json is pre-configured for Buildpad MCP server
# Just update the path to your buildpad-ui installation- Custom Agents:
@architect,@planner,@scaffold,@implement,@reviewer,@tester,@database - Prompt Templates:
/create-project,/create-feature,/add-buildpad, etc. - Project Templates: minimal, standard, enterprise
- VS Code Configuration: MCP servers, settings, launch configs
See buildpad-copilot for full documentation.
This workspace follows patterns from DaaS:
| DaaS Package | Buildpad Equivalent | Purpose |
|---|---|---|
@daas/types |
@buildpad/types |
Shared TypeScript types |
@daas/composables |
@buildpad/hooks |
Reusable React hooks |
@daas/utils |
@buildpad/services |
Utility services |
| Vue interfaces | @buildpad/ui-interfaces |
Field interface components |
v-form component |
@buildpad/ui-form |
Dynamic form component (VForm) |
| Collection views | @buildpad/ui-collections |
Dynamic form/list components |
Key Principles:
- Copy & Own - Components are copied to projects as source files
- Separation of concerns - Types, services, hooks, and UI in separate packages
- Internal workspace - Packages use
workspace:*for cross-package dependencies - Peer dependencies - React/Mantine as peer deps in shared packages
- API abstraction - Services abstract API calls for portability