Custom Fields
Custom fields let you define reusable field groups that can be referenced across multiple blocks. Think of them as field templates: define once, use everywhere.
File System Registration
Create a field.json file inside a fields/ directory in your blockstudio directory:
theme/
└── blockstudio/
└── fields/
└── hero/
└── field.json{
"$schema": "https://blockstudio.dev/schema/field",
"name": "hero",
"title": "Hero Section",
"attributes": [
{ "id": "heading", "type": "text", "label": "Heading", "default": "Hello World" },
{ "id": "description", "type": "textarea", "label": "Description" },
{ "id": "enabled", "type": "toggle", "label": "Enabled" }
]
}PHP Filter Registration
Register custom fields programmatically using the blockstudio/fields filter:
add_filter('blockstudio/fields', function ($fields) {
$fields['cta'] = [
'title' => 'Call to Action',
'attributes' => [
['id' => 'text', 'type' => 'text', 'label' => 'Button Text'],
['id' => 'url', 'type' => 'text', 'label' => 'URL'],
],
];
return $fields;
});Usage in block.json
Reference a custom field using the custom/{name} type:
{
"blockstudio": {
"attributes": [
{ "type": "custom/hero" }
]
}
}This expands inline to the fields defined in the custom field definition. The expanded fields use their original IDs (heading, description, enabled).
ID Structure
Use idStructure to prefix or transform field IDs. The {id} placeholder is replaced with the original field ID:
{
"blockstudio": {
"attributes": [
{ "type": "custom/hero", "idStructure": "hero_{id}" }
]
}
}This produces fields with IDs: hero_heading, hero_description, hero_enabled.
Overrides
Customize individual fields per-instance using overrides. Keys are the original field IDs from the definition:
{
"blockstudio": {
"attributes": [
{
"type": "custom/hero",
"idStructure": "hero_{id}",
"overrides": {
"heading": { "default": "Welcome", "label": "Title" },
"enabled": { "id": "active" }
}
}
]
}
}Override properties are merged on top of the original field definition. An id override bypasses the idStructure pattern. In the example above, enabled becomes active instead of hero_enabled.
Conditions
Conditions inside custom field definitions are automatically rewritten when
idStructure is applied. A field that conditionally depends on a sibling field
keeps working after expansion.
{
"name": "font-size",
"attributes": [
{ "id": "enable", "type": "toggle", "label": "Modify font size" },
{
"id": "min", "type": "number", "label": "Min Size",
"conditions": [[{ "id": "enable", "operator": "==", "value": true }]]
},
{
"id": "max", "type": "number", "label": "Max Size",
"conditions": [[{ "id": "enable", "operator": "==", "value": true }]]
}
]
}{ "type": "custom/font-size", "idStructure": "title_font_{id}" }Blockstudio expands this to title_font_enable, title_font_min,
title_font_max and rewrites the conditions to reference
title_font_enable instead of enable. The toggle controls work
exactly as if the fields were defined inline.
Reference-level conditions
Add conditions on the reference to apply them to every expanded field. This
is useful for hiding an entire group behind an external toggle:
{
"type": "custom/font-size",
"idStructure": "subtitle_font_{id}",
"conditions": [
[{ "id": "show_advanced", "operator": "==", "value": true }]
]
}These conditions merge with any conditions already defined inside the field
definition. Condition IDs are also rewritten via idStructure.
Multiple Custom Fields
You can use multiple custom fields in a single block, alongside regular fields:
{
"blockstudio": {
"attributes": [
{ "id": "intro", "type": "text", "label": "Intro" },
{ "type": "custom/hero", "idStructure": "hero_{id}" },
{ "type": "custom/cta", "idStructure": "cta_{id}" }
]
}
}Nesting
Custom fields work inside groups, tabs, and repeaters:
{
"blockstudio": {
"attributes": [
{
"type": "group",
"id": "content",
"title": "Content",
"attributes": [
{ "type": "custom/hero", "idStructure": "hero_{id}" }
]
}
]
}
}Additional Discovery Paths
Use the blockstudio/fields/paths filter to add additional directories for field discovery:
add_filter('blockstudio/fields/paths', function ($paths) {
$paths[] = get_stylesheet_directory() . '/blockstudio/fields';
return $paths;
});