Want a shortcut? Get going right away with Builder's Devtools, where you can register components with the flip of a switch. For details, visit Using Builder Devtools for Automated Integration.
To use your custom components in the Builder Visual Editor, you need to take a couple of minimal steps in your codebase.
The Builder SDK installed for your framework except the HTML API.
Setting up your code
To use your custom component with Builder, you need to let Builder know about it by registering your component. Registering your component makes the component appear in the Visual Editor as a custom block. Follow the steps according to framework.
Builder supports SSR and SSG out-of-the-box for all components and frameworks. However, Builder does not currently support registering React Server Components (RSCs) as custom components. You can achieve SSR using client components as described in the Next.js Client Components documentation.
For more information on SSR and custom components, visit Builder's SSR and SSG documentation.
Register your component as in the following example. Here, registerComponent() uses Next.js dynamic() to register a Heading component with two inputs, name and type, and an icon.
The options you provide to registerComponent() determine how your component appears in the Visual Editor. For example, with the image option, you can provide your own icon that the Visual Editor uses in the Insert tab. For a list of additional options, refer to Input types.
As a best practice:
For Next.js Page Router, always use dynamic() to ensure that JavaScript doesn't download unless your app uses it. Your components still render server-side.
Specify an image so the component has an icon in the Visual Editor.
For a dynamically registered component example, see the Builder Blog Example on GitHub.
Tip: If you have a prop you'd liketo make editable in the Visual Editor, be sure to define a input for it. In this example, name is editable because it is specified in the inputs array of registerComponent().
After registering your component with Builder, you can use it as in this example where an h1 uses title from the custom component, Heading.
Make sure that you import the file where Builder.registerComponent() resides into any file that has a BuilderComponent. This import is vital to the setup.
// page.tsx
import { BuilderComponent } from '@builder.io/react'
// IMPORTANT: import the file that you call Builder.registerComponent
// anywhere you have <BuilderComponent />
import '../builder-registry'
export default function Page() {
return <BuilderComponent ... />
}
As a complement to the written content in this document, the following video covers the process of integrating with Next.js along with commentary and audio instruction.
All commands and code snippets are available further down the page.
Builder supports SSR and SSG out-of-the-box for all components and frameworks. However, Builder does not currently support registering React Server Components (RSCs) as custom components. You can achieve SSR using client components as described in the Next.js Client Components documentation.
For more information on SSR and custom components, visit Builder's SSR and SSG documentation.
Register your component with Builder so you can use it in the Visual Editor. Specify:
the component
any inputs for editable properties
This makes a component, such as the example MyFunComponent, available as a custom block in Builder, so teammates can use and edit the name input of the component.
Tip: If you have a prop you'd liketo make editable in the Visual Editor, be sure to define an input for it. In this example, name is editable because it is specified in the inputs array.
Pass any registered components to the Content component.
import { Content } from '@builder.io/sdk-react';
import { customComponents } from './your-custom-components';
export default function App() {
return (
<Content
model="page"
content={YOUR_CONTENT}
apiKey={YOUR_API_KEY}
customComponents={customComponents} // <-- Add component here
/>
);
}
Builder supports SSR and SSG out-of-the-box for all components and frameworks. However, Builder does not currently support registering React Server Components (RSCs) as custom components. You can achieve SSR using client components as described in the Next.js Client Components documentation.
For more information on SSR and custom components, visit Builder's SSR and SSG documentation.
Register your component with Builder so you can use it in the Visual Editor. Specify:
the component
any inputs for editable properties
This makes a component, such as the example MyFunComponent, available as a custom block in Builder, so teammates can use and edit the name input of the component.
// builder-registry.ts
import { Builder } from '@builder.io/react'
Builder.registerComponent(
dynamic(() => import('./components/myFunComponent')),
{
name: 'myFunComponent',
inputs: [{ name: 'text', type: 'string', defaultValue: 'Hello, Builder!' }],
defaults: {
//defaultStyles
},
/* For more information on options:
* https://www.builder.io/c/docs/register-components-options
*/
}
)
Builder supports SSR and SSG out-of-the-box for all components and frameworks. However, Builder does not currently support registering React Server Components (RSCs) as custom components. You can achieve SSR using client components as described in the Next.js Client Components documentation.
For more information on SSR and custom components, visit Builder's SSR and SSG documentation.
Register your component with Builder so you can use it in the Visual Editor. Specify:
the component
any inputs for editable properties
This makes a component, such as the example MyFunComponent, available as a custom block in Builder, so teammates can use and edit the name input of the component.
Tip: If you have a prop you'd liketo make editable in the Visual Editor, be sure to define an input for it. In this example, name is editable because it is specified in the inputs array.
Pass any registered components to the Content component.
import { Content } from '@builder.io/sdk-react';
import { customComponents } from './your-custom-components';
export default function App() {
return (
<Content
model="page"
content={YOUR_CONTENT}
apiKey={YOUR_API_KEY}
customComponents={customComponents} // <-- Add component here
/>
);
}
Builder supports SSR and SSG out-of-the-box for all components and frameworks. However, Builder does not currently support registering React Server Components (RSCs) as custom components. You can achieve SSR using client components as described in the Next.js Client Components documentation.
For more information on SSR and custom components, visit Builder's SSR and SSG documentation.
You can use a component you already have or create a component that you want to register with Builder. This example uses a Heading component that displays a title prop.
Register your component as in the following example. Here, registerComponent() registers a Heading component with one text input: title
Make sure that you import the file where Builder.registerComponent() resides into any file that has a BuilderComponent. This import is vital to the setup.
import { Builder } from '@builder.io/react'
// Make sure that every page where renders Builder
// content calls the file containing this function call
Builder.registerComponent(Heading, {
name: 'Heading',
inputs: [{ name: 'title', type: 'text' }],
image: 'https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2F6bef27ee40d24f3b88239fd7e616f82a'
})
The registerComponent(component, options) method takes two arguments:
component: such as Heading
options: an object with which you can specify property values such as children, requirements, and inputs
The options you provide to registerComponent() determine how your component appears in the Visual Editor. For example, with the image option, you can provide your own icon that the Visual Editor uses in the Insert tab. For a list of additional options, refer to Input types.
As a best practice, always specify an image to use as an icon in the Visual Editor.
After registering your component with Builder, you can use it as in this example where an h1 uses title from the custom component, Heading.
Tip: If you have a prop you'd liketo make editable in the Visual Editor, be sure to define an input for it. In this example, name is editable because it is specified in the inputs array of registerComponent().
Builder supports SSR and SSG out-of-the-box for all components and frameworks. However, Builder does not currently support registering React Server Components (RSCs) as custom components. You can achieve SSR using client components as described in the Next.js Client Components documentation.
For more information on SSR and custom components, visit Builder's SSR and SSG documentation.
Register your component with Builder so you can use it in the Visual Editor. Specify:
the component
any inputs for editable properties
This makes a component, such as the example MyFunComponent, available as a custom block in Builder, so teammates can use and edit the name input of the component.
// your-custom-components.ts (React version)
import { type RegisteredComponent } from "@builder.io/sdk-react";
export const customComponents: RegisteredComponent[] = [
{
component: MyFunComponent,
// ---> You could also lazy load your component using:
// component: React.lazy(() => import('./MyFunComponent')),
name: 'MyFunComponent',
inputs: [
{
name: 'text',
type: 'string',
defaultValue: 'Hello world',
},
],
},
];
Tip: If you have a prop you'd liketo make editable in the Visual Editor, be sure to define an input for it. In this example, name is editable because it is specified in the inputs array.
Pass any registered components to the Content component.
import { Content } from '@builder.io/sdk-react';
import { customComponents } from './your-custom-components';
export default function App() {
return (
<Content
model="page"
content={YOUR_CONTENT}
apiKey={YOUR_API_KEY}
customComponents={customComponents} // <-- Add component here
/>
);
}
Builder supports SSR and SSG out-of-the-box for all components and frameworks. However, Builder does not currently support registering React Server Components (RSCs) as custom components. You can achieve SSR using client components as described in the Next.js Client Components documentation.
For more information on SSR and custom components, visit Builder's SSR and SSG documentation.
Register your component with Builder so you can use it in the Visual Editor. Specify:
the component
any inputs for editable properties
This makes a component, such as the example MyFunComponent, available as a custom block in Builder, so teammates can use and edit the name input of the component.
// for example, in my-custom-components.ts
import { type RegisteredComponent } from "@builder.io/sdk-react";
import { MyFunComponent } from "./MyFunComponent";
export const customComponents: RegisteredComponent[] = [
{
component: MyFunComponent,
// ---> You could also lazy load your component using:
// component: React.lazy(() => import('./MyFunComponent')),
name: 'MyFunComponent',
inputs: [
{
name: 'text',
type: 'string',
defaultValue: 'Hello world',
},
],
},
];
Tip: If you have a prop you'd liketo make editable in the Visual Editor, be sure to define an input for it. In this example, name is editable because it is specified in the inputs array.
Pass any registered components to the Content component.
// for example, in $.tsx
import { Content } from '@builder.io/sdk-react';
import { customComponents } from './your-custom-components';
export default function App() {
return (
<Content
model="page"
content={YOUR_CONTENT}
apiKey={YOUR_API_KEY}
customComponents={customComponents} // <-- Add component here
/>
);
}
Builder supports SSR and SSG out-of-the-box for all components and frameworks. However, Builder does not currently support registering React Server Components (RSCs) as custom components. You can achieve SSR using client components as described in the Next.js Client Components documentation.
For more information on SSR and custom components, visit Builder's SSR and SSG documentation.
The following example adds a counter as a demo custom component.
In your Remix app, add the Builder and React imports.
Register your component with Builder's registerComponent() and use RemixBrowser to create a client-side entry point for Remix as in the following example.
import { RemixBrowser } from '@remix-run/react';
import { startTransition, StrictMode } from 'react';
import { hydrateRoot } from 'react-dom/client';
import { Builder } from '@builder.io/react';
// import your custom component from your components folder
import Counter from './components/Counter/Counter';
// register your component on your entry.client.tsx file.
Builder.registerComponent(Counter, {
name: 'Counter',
// image is an icon for the custom component
image: 'https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2F0b6d99d8611d4c1da248745b718a4208',
inputs: [
{
name: 'title',
type: 'text',
},
],
});
// Begin hydration and use `RemixBrowser` to create
// client-side entry point for Remix:
function hydrate() {
startTransition(() => {
hydrateRoot(
document,
<StrictMode>
<RemixBrowser />
</StrictMode>
);
});
}
// Hydrate when the browser is idle.
if (typeof requestIdleCallback === 'function') {
requestIdleCallback(hydrate);
} else {
// Safari doesn't support requestIdleCallback() so
// use setTimeout() to start hydration after a brief delay.
// https://caniuse.com/requestidlecallback
setTimeout(hydrate, 1);
}
After importing your component, register it with Builder. Builder.registerComponent() takes two parameters:
the custom component, Counter,
an object with metadata about the Counter, here, name, image, and inputs.
Use RemixBrowser to create a client-side entry point for Remix and begin hydration to improve performance by rendering components as needed:
hydrate() attaches RemixBrowser to HTML and hydrates it with JavaScript to make it interactive.
startTransition() batches updates and renders components as needed.
hydrateRoot() attaches the component to the HTML and hydrates it to add interactivity to initial HTML from server.
The if statement at the end uses requestIdleCallback() so that hydrate() is only called when the browser is idle, which helps reduce how long the application takes to load.
For more information on hydration, see the React hydrateRoot() documentation.
The if statement at the end uses requestIdleCallback() so that hydrate() is only called when the browser is idle, which helps reduce how long the application takes to load.
The specifications you provide to registerComponent() determine how your component appears in the Visual Editor. For example, with the image option, you can provide your own icon that the Visual Editor uses in the Insert tab.
As a best practice, always specify an image, so the component has an icon in the Visual Editor.
For a list of additional options, refer to Input types.
Tip: If you have a prop you'd liketo make editable in the Visual Editor, be sure to define an input for it. In this example, name is editable because it is specified in the inputs array of registerComponent().
Builder supports SSR and SSG out-of-the-box for all components and frameworks. However, Builder does not currently support registering React Server Components (RSCs) as custom components. You can achieve SSR using client components as described in the Next.js Client Components documentation.
For more information on SSR and custom components, visit Builder's SSR and SSG documentation.
Register your component with Builder so you can use it in the Visual Editor. Specify:
the component
any inputs for editable properties
This makes a component, such as the example MyFunComponent, available as a custom block in Builder, so teammates can use and edit the name input of the component.
// your-custom-components.ts (React version)
import { type RegisteredComponent } from "@builder.io/sdk-react";
export const customComponents: RegisteredComponent[] = [
{
component: MyFunComponent,
// ---> You could also lazy load your component using:
// component: React.lazy(() => import('./MyFunComponent')),
name: 'MyFunComponent',
inputs: [
{
name: 'text',
type: 'string',
defaultValue: 'Hello world',
},
],
},
];
Tip: If you have a prop you'd liketo make editable in the Visual Editor, be sure to define an input for it. In this example, name is editable because it is specified in the inputs array.
Pass any registered components to the Content component.
import { Content } from '@builder.io/sdk-react';
import { customComponents } from './your-custom-components';
export default function App() {
return (
<Content
model="page"
content={YOUR_CONTENT}
apiKey={YOUR_API_KEY}
customComponents={customComponents} // <-- Add component here
/>
);
}
Builder supports SSR and SSG out-of-the-box for all components and frameworks. However, Builder does not currently support registering React Server Components (RSCs) as custom components. You can achieve SSR using client components as described in the Next.js Client Components documentation.
For more information on SSR and custom components, visit Builder's SSR and SSG documentation.
The following example adds a counter as a demo custom component.
In your Remix app, add the Builder and React imports.
Register your component with Builder's registerComponent() and use RemixBrowser to create a client-side entry point for Remix as in the following example.
import { RemixBrowser } from '@remix-run/react';
import { startTransition, StrictMode } from 'react';
import { hydrateRoot } from 'react-dom/client';
import { Builder } from '@builder.io/react';
// import your custom component from your components folder
import Counter from './components/Counter/Counter';
// register your component on your entry.client.tsx file.
Builder.registerComponent(Counter, {
name: 'Counter',
// image is an icon for the custom component
image: 'https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2F0b6d99d8611d4c1da248745b718a4208',
inputs: [
{
name: 'title',
type: 'text',
},
],
});
// Begin hydration and use `RemixBrowser` to create
// client-side entry point for Remix:
function hydrate() {
startTransition(() => {
hydrateRoot(
document,
<StrictMode>
<RemixBrowser />
</StrictMode>
);
});
}
// Hydrate when the browser is idle.
if (typeof requestIdleCallback === 'function') {
requestIdleCallback(hydrate);
} else {
// Safari doesn't support requestIdleCallback() so
// use setTimeout() to start hydration after a brief delay.
// https://caniuse.com/requestidlecallback
setTimeout(hydrate, 1);
}
After importing your component, register it with Builder. Builder.registerComponent() takes two parameters:
the custom component, Counter,
an object with metadata about the Counter, here, name, image, and inputs.
Use RemixBrowser to create a client-side entry point for Remix and begin hydration to improve performance by rendering components as needed:
hydrate() attaches RemixBrowser to HTML and hydrates it with JavaScript to make it interactive.
startTransition() batches updates and renders components as needed.
hydrateRoot() attaches the component to the HTML and hydrates it to add interactivity to initial HTML from server.
The if statement at the end uses requestIdleCallback() so that hydrate() is only called when the browser is idle, which helps reduce how long the application takes to load.
For more information on hydration, see the React hydrateRoot() documentation.
The if statement at the end uses requestIdleCallback() so that hydrate() is only called when the browser is idle, which helps reduce how long the application takes to load.
The specifications you provide to registerComponent() determine how your component appears in the Visual Editor. For example, with the image option, you can provide your own icon that the Visual Editor uses in the Insert tab.
As a best practice, always specify an image, so the component has an icon in the Visual Editor.
For a list of additional options, refer to Input types.
Tip: If you have a prop you'd liketo make editable in the Visual Editor, be sure to define an input for it. In this example, name is editable because it is specified in the inputs array of registerComponent().
Use your component in your code by exporting and returning your component. Notice that within Content you reference your custom components with customComponents={CUSTOM_COMPONENTS}.
Register your component as in the following example. The next snippet registers a custom component with Builder by defining an array CUSTOM_COMPONENTS that includes the CustomComponent, specifying its name and the props it accepts, text as a string, which makes it available for use within Builder's Visual Editor.
Next, add your custom component to the Content component. This example displays a message and conditionally renders Builder.io content within a view.
If shouldRenderBuilderContent is true, it uses the Content component from Builder.io's React Native SDK to render content specified by content, with an apiKey and custom components defined in CUSTOM_COMPONENTS.
As a best practice, always specify an image to use as an icon in the Visual Editor.
Tip: If you have a prop you'd liketo make editable in the Visual Editor, be sure to define an input for it. In this example, name is editable because it is specified in the inputs array of CUSTOM_COMPONENTS.
This example uses a standalone Angular component for a custom heading component in an integrated app. If your Angular app isn't already integrated with Builder, check the Quickstart for the fastest way to get going.
Define the component's selector, template, and any input properties that you want to be editable in the Builder Visual Editor. In this case, because the title is intended for editing by end user, create an Angular @Input() for it.
// heading.component.ts
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-heading',
standalone: true,
template: `<h1>This is my heading: {{ title }}</h1>`
// ...other component metadata properties
})
export class HeadingComponent {
// add inputs for editable properties
@Input() title!: string;
}
In the component where you're using the <builder-content> component, for example, BuilderPage, import the customComponents array from, for example, builder-registry.ts, and assign it to the customComponents property.
Pass this customComponents property to the <builder-content> component to make your custom components available in the Builder Visual Editor.
// app/components/builder-page.component.ts
// ...other imports here
import { Content } from "@builder.io/sdk-angular";
import { customComponents } from "../builder-registry";
@Component({
selector: "app-builder-page",
standalone: true,
imports: [Content, CommonModule],
// pass customComponents to builder-content
template: `
<ng-container *ngIf="content || isPreviewing; else notFound">
<builder-content
[model]="model"
[content]="content"
[apiKey]="apiKey"
[customComponents]="customComponents"
></builder-content>
</ng-container>
`,
})
export class BuilderPage {
// assign the customComponents array to the customComponents property
customComponents = customComponents;
// fetch content from Builder
// ...
}
Define your custom component. This example defines custom components in builder-registry.ts, which exports a RegisteredComponent array of objects, one of which is the example HeadingComponent.
// builder-registry.ts
import type { RegisteredComponent } from "@builder.io/sdk-angular";
import { HeadingComponent } from "./heading/heading.component";
export const customComponents: RegisteredComponent[] = [
{
component: HeadingComponent,
name: "Heading",
//@ts-ignore -- Required for @builder.io/sdk v5.0.0 when using meta property with Angular
meta: {
selector: 'app-heading',
standalone: true
},
inputs: [
{
name: 'title',
type: 'string',
defaultValue: 'I am a heading',
},
],
},
// other custom components here ...
];
When registering components in Angular, there are a couple of points to keep in mind:
Specify the meta object with your component’s selector and standalone: true.
For SDK versions prior to version 5, make sure you put @ts-ignore before meta. After version 5, you can omit @ts-ignore.
To enhance your component's usability in the Visual Editor:
Add an image property to provide an icon, making your component easily identifiable.
Define any properties you want users to edit in the inputs array. For example, the name property becomes editable in the Visual Editor because it's specified in the inputs array.
This example uses a standalone Angular component for a custom heading component in an integrated app. If your Angular app isn't already integrated with Builder, check the Quickstart for the fastest way to get going.
Define the component's selector, template, and any input properties that you want to be editable in the Builder Visual Editor. In this case, because the title is intended for editing by end user, create an Angular @Input() for it.
// heading.component.ts
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-heading',
standalone: true,
template: `<h1>This is my heading: {{ title }}</h1>`
// ...other component metadata properties
})
export class HeadingComponent {
// add inputs for editable properties
@Input() title!: string;
}
In the component where you're using the <builder-content> component, for example, BuilderPage, import the customComponents array from, for example, builder-registry.ts, and assign it to the customComponents property.
Pass this customComponents property to the <builder-content> component to make your custom components available in the Builder Visual Editor.
// app/components/builder-page.component.ts
// ...other imports here
import { Content } from "@builder.io/sdk-angular";
import { customComponents } from "../builder-registry";
@Component({
selector: "app-builder-page",
standalone: true,
imports: [Content, CommonModule],
// pass customComponents to builder-content
template: `
<ng-container *ngIf="content || isPreviewing; else notFound">
<builder-content
[model]="model"
[content]="content"
[apiKey]="apiKey"
[customComponents]="customComponents"
></builder-content>
</ng-container>
`,
})
export class BuilderPage {
// assign the customComponents array to the customComponents property
customComponents = customComponents;
// fetch content from Builder
// ...
}
Define your custom component. This example defines custom components in builder-registry.ts, which exports a RegisteredComponent array of objects, one of which is the example HeadingComponent.
// builder-registry.ts
import type { RegisteredComponent } from "@builder.io/sdk-angular";
import { HeadingComponent } from "./heading/heading.component";
export const customComponents: RegisteredComponent[] = [
{
component: HeadingComponent,
name: "Heading",
//@ts-ignore -- Required for @builder.io/sdk v5.0.0 when using meta property with Angular
meta: {
selector: 'app-heading',
standalone: true
},
inputs: [
{
name: 'title',
type: 'string',
defaultValue: 'I am a heading',
},
],
},
// other custom components here ...
];
When registering components in Angular, there are a couple of points to keep in mind:
Specify the meta object with your component’s selector and standalone: true.
For SDK versions prior to version 5, make sure you put @ts-ignore before meta. After version 5, you can omit @ts-ignore.
To enhance your component's usability in the Visual Editor:
Add an image property to provide an icon, making your component easily identifiable.
Define any properties you want users to edit in the inputs array. For example, the name property becomes editable in the Visual Editor because it's specified in the inputs array.
Builder supports SSR and SSG out-of-the-box for all components and frameworks. However, Builder does not currently support registering React Server Components (RSCs) as custom components. You can achieve SSR using client components as described in the Next.js Client Components documentation.
For more information on SSR and custom components, visit Builder's SSR and SSG documentation.
The registerComponent(component, options) method takes two arguments:
component: such as Heading in the following example
options: an object with which you can specify property values such as children, requirements, and inputs
The options you provide to registerComponent() determine how your component appears in the Visual Editor. For example, with the image option, you can provide your own icon that the Visual Editor uses in the Insert tab. For a list of additional options, refer to Input types.
Tip: If you have a prop you'd liketo make editable in the Visual Editor, be sure to define a input for it. In this example, name is editable because it is specified in the inputs array of registerComponent().
The following example code registers a custom component with Builder in Swift.
BuilderCustomComponent: represents your custom component and its configuration, such as its name, here MyComponentName, and inputs, here ctaText of typetext. This definition helps Builder recognize and manage your custom component.
factory closure: defines how to create an instance of your custom view, in this example HeroComponent. When Builder needs to render your component, it calls this closure, passing configuration options — such as headingText and ctaText — and styles. Inside the closure, you create and configure your custom view based on these options.
Replace YOUR_BUILDER_API_KEY with your Builder Public API Key to link the custom component registration to your Builder project.
registerComponent(component: BuilderCustomComponent(name: "MyComponentName",
inputs: [ BuilderInput(name: "ctaText", type: "text")]
), factory: { (options, styles) in
// Return an instance of your view, passing in any
// properties from Builder to your component for rendering
return HeroComponent(headingText: options["headingText"].stringValue, ctaText: options["ctaText"].stringValue)
}, YOUR_BUILDER_API_KEY);
As a complement to the written content in this document, the following video covers the process of integrating with Next.js along with commentary and audio instruction.
All commands and code snippets are available further down the page.
Configure BuilderBlock() with tag, name, and inputs. Make sure you have corresponding inputs in BuilderBlock() for each Angular @Input().
Pass in your custom component, as in BuilderBlock({...})(CustomThing).
import { Component, Input } from '@angular/core';
import { BuilderBlock } from '@builder.io/angular'; // <-- import BuilderBlock
// This is your custom component.
// Here it's called CustomThingComponent
@Component({
selector: 'app-custom-thing',
template: 'Hello: {{name}}!',
...
})
export class CustomThingComponent {
@Input()
text = ''; // <-- name Angular and Builder inputs the same
}
// Register your custom component with BuilderBlock
BuilderBlock({
tag: 'app-custom-thing', // <-- use the component selector here
name: 'Custom thing',
//@ts-ignore -- Required for @builder.io/sdk v5.0.0 when using meta property with Angular
meta: {
selector: 'app-custom-thing',
},
inputs: [
{
name: 'text', // <-- this name matches the Angular @Input() above
type: 'string',
},
],
})(CustomThingComponent);
You can define BuilderBlock() in the same file as your component or organize it in separate files based on your project structure. When registering your component, note that different properties serve different purposes:
The tag property connects your component to Builder's runtime, enabling proper integration with your Angular application.
The meta property supports Builder's code generation features, particularly for AI functionality and Figma plugin integration. For SDK versions prior to version 5, make sure you put @ts-ignore before meta. After version 5, you can omit @ts-ignore.
To enhance your component's usability in the Visual Editor:
Add an image property to provide an icon, making your component easily identifiable.
Define any properties you want users to edit in the inputs array. For example, the name property becomes editable in the Visual Editor because it's specified in the inputs array.
Your registered components, though available for use in the Visual Editor, reside in your code. Builder does not retain or store your components in any way.
When you register a component, you must provide a name. Optionally, you can also specify:
component default styling
whether Builder wraps the component in a <div>
whether the component displays in the Insert tab
The following table describes each of the additional component options:
Name
Type
Description
defaultStyles
object
Use for showing an example value in the input form when creating a new instance of this component, to users understand its purpose. Users in the Visual Editor can edit these styles.
Hide your component from the Insert tab within Builder's Visual Editor. Use this feature for deprecating a component when you want to reduce its use, but still need the component registered with Builder so that older content that uses the component continues to function properly. For more information on versioning, refer to Versioning Custom Components.
hideFromInsertMenu: true
noWrap
Boolean
By default, Builder wraps your components in a <div>.
You can opt out of this wrapping by using the noWrap option. For a full code example, see Builder's built-in form input component.
When using noWrap: true, it is important to pass {...props.attributes} to ensure class names are assigned correctly as in the following example.
The following example shows noWrap with a Material UITextField in Builder.io.
import { TextField } from '@material-ui/core'
export const BuilderTextField = props => (
// Important! Builder.io must add a couple classes
// and attributes with props.attributes.
// If you add your own classes,
// do it after ...props.attributes
<TextField
variant={props.variant}
{...props.attributes}
className={`my-class ${props.attributes.className}`}
/>
)
Builder.registerComponent(BuilderTextField, {
name: 'TextField',
noWrap: true, // Important!
inputs: [{ name: 'variant', type: 'string' }]
})
The following code snippet features a number of options in the context of registerComponent():
const HeloWorldComponent = (props) => <div>{props.text}</div>;
Builder.registerComponent(HelloWorldComponent, {
// Begin component options
// Name your component (required)
name: "Hello World",
// Optional: provide CSS in an object to defaultStyles
defaultStyles: {
textAlign: "center",
fontSize: "20px",
},
// Optional: specify whether your component is wrapped in a <div>
noWrap: true,
// Optional: specify if your component shows in the Insert tab
hideFromInsertMenu: false,
// End component options
// Begin inputs:
inputs: [{ ... }],
});
You can programmatically set bindings on custom components so you can apply multiple bindings simultaneously. This is helpful when, for example, applying styles from an existing design system. The snippet below registers a custom component with default bindings for the product title and a theme background color:
When you use Builder.registerComponent() to register custom components in Builder.io, you can provide various options to customize the behavior of your component.
One of these options is the models property, where you can specify a list of model names. By doing so, you can restrict the usage of the component to only those models listed, ensuring that the component is available only for specific purposes. If the models property is not provided, the component will be available for all models in Builder.io.
To control exactly which models your component is available in, use the models array when registering your component as in the following example:
In this example, the RelatedProducts component is only accessible in the Visual Editor when editing content entries made with the product-editorial or page models.