Buildpad Component Reference
Buildpad-First Rule (MANDATORY)
Before creating ANY custom component, check if Buildpad provides it. If available, use it via CLI.
| ❌ DO NOT Use Directly | ✅ Use Buildpad Instead |
|---|---|
useForm from @mantine/form |
VForm, CollectionForm |
<DatePicker> from @mantine/dates |
DateTime component |
<Dropzone> from @mantine/dropzone |
Files, Upload components |
<TextInput> directly |
Input component |
<Select> directly |
SelectDropdown component |
<Checkbox> directly |
SelectMultipleCheckbox |
<Switch> directly |
Toggle, Boolean components |
Custom <Table> for records |
CollectionList component |
| Custom filter UI | FilterPanel component |
Basic Mantine layout components (Stack, Group, Button, Modal, Table) are fine to use directly.
Component Catalog (40+)
Input: Input, Textarea, InputCode, Tags, RichTextHtml, RichTextMarkdown, InputBlockEditor Selection: SelectDropdown, SelectRadio, SelectMultipleCheckbox, SelectMultipleCheckboxTree, SelectMultipleDropdown, AutocompleteAPI, CollectionItemDropdown, SelectIcon Boolean: Boolean, Toggle DateTime: DateTime, Slider Files: FileInterface, FileImage, Files, Upload Media: Color, Map, MapWithRealMap Relations: ListM2M, ListM2O, ListO2M, ListM2A (+ render-prop variants: ListM2MInterface, ListM2OInterface, ListO2MInterface) Layout: Divider, Notice, GroupDetail System: SystemPermissions Collections: CollectionForm, CollectionList, CollectionListToolbar, CollectionListFooter, BulkActionsBar, DeleteConfirmModal, BottomPagination, FilterPanel Form: VForm, FormField, FormFieldLabel, FormFieldInterface Table: VTable (presentation table with sort, resize, reorder, header context menus) Workflow: WorkflowButton
Opt-in Modules (scaffolded whole via CLI)
These are ready-made, multi-screen experiences — installed with their own CLI command, not composed by hand. Use the dedicated skill for each.
| Module | Package | Screens / API | Skill |
|---|---|---|---|
| Files | @buildpad/ui-files |
FileManager (/files library) + FileDetail (/files/[id]); useFiles, useFolders hooks; getAssetUrl thumbnails |
add-files |
| Form Builder | @buildpad/ui-forms |
FormBuilder (visual author) + DynamicForm (runtime); FormDefinition model in fb_definitions; useFormDefinitions hook |
create-form-builder |
Note the naming: the field-level Files/Upload widgets and the VForm/CollectionForm runtime above are the substrate; FileManager/FileDetail and FormBuilder/DynamicForm are the full modules built on top of them.
Available Hooks
// Auth
import { useAuth, usePermissions } from "@/lib/buildpad/hooks";
// Relations
import { useRelationM2M, useRelationM2MItems } from "@/lib/buildpad/hooks";
import { useRelationM2O, useRelationM2OItem } from "@/lib/buildpad/hooks";
import { useRelationO2M, useRelationO2MItems } from "@/lib/buildpad/hooks";
import { useRelationM2A, useRelationM2AItems } from "@/lib/buildpad/hooks";
// Utilities
import {
useFiles,
useSelection,
usePreset,
useEditsGuard,
} from "@/lib/buildpad/hooks";
// Versioning & Workflow
import {
useVersions,
useWorkflowAssignment,
useWorkflowVersioning,
} from "@/lib/buildpad/hooks";
Utility Functions
import { isNewItem, isExistingItem } from "@/lib/buildpad/utils";
| Function | Description |
|---|---|
isNewItem(id) |
Returns true for "+", "%2B", "new", null, undefined, "". Use this everywhere instead of inline id === "+" checks. |
isExistingItem(id) |
Inverse of isNewItem() with type guard — narrows to string | number. |
MANDATORY: Always use isNewItem() in detail pages and any code that checks if an item is being created vs edited. Never write id === "+" or id === "%2B" inline — the utility handles all sentinel values including URL-encoded variants.
CollectionForm Usage
import { CollectionForm } from '@/components/ui/collection-form';
// Create mode
<CollectionForm collection="articles" => router.push(`/articles/${item.id}`)} />
// Edit mode
<CollectionForm collection="articles" id={itemId} mode="edit" />
CollectionForm automatically fetches schema, renders all 40+ field types, handles validation and submission.
CollectionList Usage (MANDATORY for ALL Listing Views)
Every page or module that displays a list of collection records MUST use CollectionList.
Do NOT build custom tables with Mantine <Table> or raw <table> for collection data.
CollectionList provides a complete content-module-style layout:
- Action toolbar (CollectionListToolbar) with search, filter toggle, archive filter dropdown, refresh, bulk actions, and create button
- Integrated
FilterPanelwith active filter count badge - Permission-gated create button and bulk actions (disabled with "Not allowed" tooltip when lacking permission)
- Built-in CRUD permission gating (auto-fetches
GET /permissions/me, disables buttons when not allowed) - Built-in delete workflow with confirmation modal, API call, and auto-refresh via
enableDelete - Pagination with configurable page sizes (10, 25, 50, 100) and item count display (CollectionListFooter)
- Field-type-aware cell rendering (booleans → ✓/✗, dates → formatted, numbers → localized, JSON → badge, UUID → truncated with tooltip)
- Column sorting, resizing, reordering via VTable composition
- Archive filtering (all/archived/unarchived) when
archiveFieldis set
CRUD permissions are handled automatically — do not manually gate create/delete buttons or pass permission state. Use bulkActions only for custom operations beyond CRUD (e.g., Archive, Export).
Full-Featured CollectionList (preferred pattern)
import { CollectionList } from "@/components/ui";
<CollectionList
collection="articles"
enableSearch
enableFilter
enableSelection
enableCreate
enableDelete
enableSort
enableResize
enableReorder
enableHeaderMenu
archiveField="status"
archiveValue="archived"
unarchiveValue="draft"
limit={25}
=> router.push(`/content/articles/+`)}
=> router.push(`/content/articles/${item.id}`)}
/>;
BulkAction Interface (for custom operations beyond CRUD)
interface BulkAction {
label: string;
icon?: React.ReactNode;
color?: string;
confirm?: boolean;
/** When set, the action button is disabled if the user lacks this permission */
requiredPermission?: "create" | "update" | "delete";
action: (selectedIds: (string | number)[]) => void | Promise<void>;
}
Permission-Aware Patterns
CollectionList and CollectionForm automatically resolve CRUD permissions from GET /permissions/me:
- Admin bypass: users whose policies grant
admin_access(detected viaPermissionsService.isAdmin) get full CRUD access and see all fields regardless of per-collection permissions - Create button: disabled with tooltip when user lacks create permission
- Bulk actions: individually disabled based on
requiredPermissionfield - Delete button: built-in delete with confirmation when
enableDeleteis set (requires delete permission) - Field visibility: columns filtered to only readable fields (admins see all fields)
- Archive actions: requires both update permission and archive field access
// Permission state can be observed via callback
<CollectionList
collection="articles"
enableCreate
=> router.push("/content/articles/+")}
=> {
// perms: { createAllowed, readAllowed, updateAllowed, deleteAllowed, archiveAllowed }
console.log("Can create:", perms.createAllowed);
}}
/>
Component Dependencies
| Component | Requires |
|---|---|
| file-image, file, files | upload |
| list-m2m, list-m2o, list-o2m, list-m2a | hooks, services, collection-form, collection-list |
| vform | ALL interface components (32+) |
| collection-form | vform + all interfaces |
| collection-list | vtable (VTable), filter-panel, collection-list-toolbar, collection-list-footer, bulk-actions-bar, delete-confirm-modal |
| filter-panel | types |
References
- React component patterns