Create your own block type
Use a custom block type when a design recurs and editors should fill in fields instead of arranging its pieces. Each placed block keeps its own content; the type owns the shared structure and styling. This is a built-in CMS feature in Cloud and self-hosting, not a Typeroll App or Extension.
From Core 0.2.78, write/editor permission can create or change a type. Editors can also place available types and edit their values. No local development environment is required.
First choose the simplest approach
Section titled “First choose the simplest approach”- For a one-off layout, combine built-in blocks.
- For the same content everywhere, use a global block.
- For a section copied and edited independently, use a block template.
- For a reusable design with editable fields, create a block type.
Prefer a composed type, built from existing blocks. It keeps their image, link, named-style and responsive behavior. Use a template type with your own HTML when built-in pieces cannot express the markup you need. A template block type is unrelated to a full Page template.
Recommended: ask your AI agent
Section titled “Recommended: ask your AI agent”Creating custom block types is a good task to delegate to an AI agent connected to Typeroll through MCP. Describe the design, which fields people should edit and how it should behave on mobile. The agent can inspect existing blocks and starters, define the fields, build the composition or markup, and validate and preview it with Typeroll’s tools. You do not need to write the JSON, HTML or CSS yourself.
For example:
Create a reusable advice callout for this Site and Version. Give editors aheading and advice text to fill in. Use our existing colors and spacing,and compose it from built-in blocks if possible. Check whether a suitable typealready exists before creating one. Validate the definition, preview it withshort and long text, and place an example on a draft Page for me to review.Do not deploy the site.The agent uses your current Site permissions. From Core 0.2.78, write/editor access is enough to create or change a block type; administrator access is not required. Read-only access cannot save changes. The optional tr-custom-blocks recipe guides this workflow. With compact MCP discovery, ask the agent to discover the relevant tools as needed. A local repository or development server is not required.
Review the result in the editor, test its fields and inspect narrow and wide previews. Once the type is available, editors can add instances and change their content without asking an agent or editing code. Have an administrator review any custom script and test interactions before publication.
The definition and tool sequence below are references for your agent or for manual API work; you do not need to enter them by hand.
Alternative: create it in the portal
Section titled “Alternative: create it in the portal”- Select the Site and open Blocks. Create a block type and choose a starter such as an icon list, feature cards or numbered steps.
- Give it a machine name and a clear label. Define the fields editors should change, rather than exposing the entire layout as HTML.
- Adapt its composition, or use Turn into block type… on an existing section in the page editor and select which values become fields.
- Use Preview with realistic text, empty optional fields and long values. Check the available narrow and wide preview sizes. Resolve validation errors.
- Save the type, return to a Page and add it from the block library. Edit its fields, save the Page and preview it in context before publishing.
Example: an editable advice callout
Section titled “Example: an editable advice callout”This definition exposes a heading and a paragraph. The heading remains an H2;
editors do not need to rebuild the design. It can be passed directly to
create_block_type, or to POST /api/v1/sites/{siteId}/block-types.
{ "name": "advice_callout", "label": "Advice callout", "category": "content", "schema": [ { "name": "heading", "type": "text", "label": "Heading", "required": true }, { "name": "message", "type": "text", "label": "Advice", "required": true } ], "composition": [ { "id": "callout", "type": "core/container", "data": { "direction": "column", "gap": "sm", "css_class": "advice-callout" }, "children": [ { "id": "heading", "type": "core/heading", "data": { "text": "{{props.heading}}", "level": "h2" } }, { "id": "message", "type": "core/text", "data": { "text": "{{props.message}}" } } ] } ], "styles": ".advice-callout { border-inline-start: 4px solid var(--color-primary); padding: 1.25rem; }"}A binding such as {{props.heading}} connects an editor field to an inner block.
Whole-value bindings preserve types: arrays remain arrays and booleans remain
booleans. Use core/text for plain field values and core/prose for rich text.
Validate, preview, then save
Section titled “Validate, preview, then save”- Call
list_block_typesandread_block_typefor the blocks you will use.list_block_type_startersreturns complete definitions you can adapt. - Call
validate_block_typewith the definition underdefinition. Errors include paths such as/schema/0/name; fix them before continuing. - Call
preview_block_typewith the samedefinitionand sampledata: { "heading": "Before you begin", "message": "Measure the doorway." }. Inspect the returneddocumentvisually. Try long and missing values too. - Call
create_block_typewith the definition’s top-level properties. Use the returnedblock_type.idwhen placing an instance. - Call
add_blockfor the intended Page, using:
{ "page_id": "YOUR_PAGE_ID", "block": { "type": "advice_callout", "data": { "heading": "Before you begin", "message": "Measure the doorway." } }}Read the Page again, save its working copy and preview before deployment.
For a site version, pass the same version to all supported tools.
When you need custom HTML
Section titled “When you need custom HTML”Use the same fields, but replace composition with template:
<aside class="advice-callout"> {{#heading}} <h2>{{heading}}</h2> {{/heading}} {{#message}} <p>{{message}}</p> {{/message}}</aside>{{heading}} is escaped text; the surrounding section omits its markup when
empty. Rich-text fields can use triple braces. Repeating groups use
{{#each items}}; link fields support a helper that avoids empty links.
See the full field and template syntax.
CSS is scoped to the block. Prefer the site’s variables and
named styles so the component follows the site’s design.
Custom markup is sanitized; putting a script tag in it does not enable JavaScript.
A separate script property is executable code and needs deliberate code review.
The unsaved block preview does not execute scripts, so verify interactions in
an appropriate test deployment as well. See the
script permission rules.
Maintain and share the type
Section titled “Maintain and share the type”Changing the definition affects every instance at the next deployment. Before
an update, inspect Usage or call find_pages_using_block_type. Rename fields
with the supported renames mapping so stored values follow the change; do not
silently remove and recreate fields. Removing populated fields or changing their
type can require explicit data-loss confirmation.
Export and import .tcblocks packages to reuse a type on another Site. Review
imported HTML, CSS and scripts before accepting them. Deleting a type in use is
blocked; replace its instances first.
For a new type, an AI agent can propose its schema, composition and responsive behavior from your brief, then validate it and show a preview. Inspect existing uses before changing a shared definition. See Personal AI connections.
Check it
Section titled “Check it”validate_block_type reports no errors for the definition, and
preview_block_type renders it with sample data at the widths you support.
Before changing a type that is already in use, find_pages_using_block_type
lists the Pages to review.