Defining components
A component is a user-definable block type. Each key in
config.components is a component name that appears in the Blocks
palette and in the saved document’s type field.
import type { Config } from "@useblok/core";
const config: Config = {
components: {
Hero: { /* see below */ },
Features: { /* ... */ },
},
};ComponentConfig shape
interface ComponentConfig<Props> {
label?: string; // Shown in the library + inspector
description?: string; // Short subtitle in the library
icon?: ReactNode; // Rendered in library row + layers tree
accent?: string; // Color for the icon tile (any CSS color)
folder?: string; // Groups in the Blocks palette
tags?: string[]; // Used by library search
fields?: Fields<Props>; // Auto-form definition
tabs?: TabConfig[]; // Optional grouping of fields
defaultProps?: Props; // Values used when the block is inserted
render: ComponentType<Props>;// Canvas renderer — required
preview?: ReactNode; // Optional palette thumbnail
getSummary?: (p: Props) => string; // Shown in Layers + row headings
version?: number; // Current schema version (default 0)
migrations?: BlockMigration[]; // See the Migrations page
}Minimal example
Hero: {
label: "Hero",
fields: {
title: { type: "text", label: "Title", required: true },
},
defaultProps: { title: "Hello" },
render: ({ title }) => <h1>{title}</h1>,
}Richer example
Hero: {
label: "Hero",
description: "Big banner with headline, subtitle, and CTA.",
icon: <Sparkles size={16} />,
accent: "#6366f1",
folder: "Marketing",
tags: ["banner", "top", "landing"],
tabs: [
{ id: "content", label: "Content" },
{ id: "style", label: "Style" },
],
fields: {
title: { type: "text", label: "Title", tab: "content", required: true },
subtitle: { type: "textarea", label: "Subtitle", tab: "content", rows: 3 },
cta: { type: "link", label: "Button", tab: "content" },
align: { type: "select", label: "Alignment", tab: "style",
options: [
{ label: "Left", value: "left" },
{ label: "Center", value: "center" },
]
},
},
defaultProps: { title: "Hello", subtitle: "", align: "center" },
render: ({ title, subtitle, cta, align }) => (
<section style={{ textAlign: align, padding: 48 }}>
<h1>{title}</h1>
{subtitle && <p>{subtitle}</p>}
{cta?.url && <a href={cta.url}>{cta.label}</a>}
</section>
),
getSummary: (p) => p.title as string,
}render — the canvas component
Your render function receives the block’s props object. It’s a
regular React component — render whatever you want.
render: (props) => (
<section>
<h1>{props.title}</h1>
{props.subtitle && <p>{props.subtitle}</p>}
</section>
)The blok helper (slots)
If your block has a slot field, the render function receives an extra
blok helper with a renderSlot(name) method:
Container: {
fields: { children: { type: "slot" } },
render: ({ blok }) => (
<div style={{ padding: 24 }}>
{blok.renderSlot("children")}
</div>
),
}See the root component page for how the
root’s children plugs in.
defaultProps
Used as the initial prop values when the block is inserted from the
palette. A block’s id is generated automatically — don’t include it
in defaultProps.
defaultProps: { title: "Hello", subtitle: "", align: "center" }getSummary
Short label (usually the block’s main text) shown in:
- The Layers tree
- The Edit panel row header
- The breadcrumb when drilling into slots
getSummary: (props) => props.title as stringReturn an empty string (or omit the function) if no sensible summary exists.
version + migrations
When your props shape changes in a backwards-incompatible way (renamed
field, restructured object), bump version and add a migration. See
Migrations.
Type-safe components
For full prop autocomplete and type-checking in render, fields, and
defaultProps, pass the props type as a generic:
type HeroProps = { title: string; subtitle: string; align: "left" | "center" };
const Hero: ComponentConfig<HeroProps> = {
label: "Hero",
fields: {
title: { type: "text", label: "Title" },
subtitle: { type: "textarea", label: "Subtitle" },
align: { type: "select", label: "Alignment", options: [...] },
},
defaultProps: { title: "Hello", subtitle: "", align: "center" },
render: ({ title, subtitle, align }) => <section>{/* ... */}</section>,
};Categories
Organise the Blocks palette:
categories: {
marketing: { title: "Marketing", description: "Hero, CTAs, grids." },
layout: { title: "Layout" },
}Components are placed in categories by their folder field. You can also
set components: ["Hero", "Features"] on a category for an explicit list.