> This page is for Developer.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.makeswift.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.makeswift.com/_mcp/server.

# registerComponent

> Adds your components to the Makeswift builder.

Adds your components to the Makeswift builder.

## Arguments

**`component`** `Component` — required

Your component to be registered. This can be a React component or a function.

---

**`options`** `object` — required

Options for site version and locale.

#### properties

**`type`** `string` — required

A unique string that identifies the component for Makeswift to
render. Don't change the type once you use the component in
the Makeswift builder.

> **Warning**
>
> If this value changes after you use the component in the Makeswift builder, the component will appear as a "Component not found" block. To fix this, restore the `type` to the original value, or delete this component and re-add add it to the page.

---

**`label`** `string` — required

The label shown in the Makeswift builder.

---

**`description`** `string`

The description shown in the Panel of the Makeswift builder. This can be written in Markdown format.
Added in [`v0.24.8`](https://github.com/makeswift/makeswift/releases/tag/%40makeswift%2Fruntime%400.24.8).

---

**`icon`** `string`

The icon shown in the Makeswift builder. You can find all available icons in the [icons list](#icons-list) section.

---

**`hidden`** `boolean`

A boolean that determines whether or not this component will be displayed in the Component Tray.

---

**`builtinSuspense`** `boolean`

A boolean that determines whether or not this component will be wrapped in a built-in `<Suspense>` boundary.
Defaults to `true`. Set this to `false` if your component already includes its own `<Suspense>` boundary.

Added in [`v0.26.0`](https://github.com/makeswift/makeswift/releases/tag/%40makeswift%2Fruntime%400.26.0).

---

**`props`** `Record<string, Control>` — required

An object mapping prop names to Makeswift [controls](/developer/docs/get-started/concepts#controls).

---

---

## Examples

### Registering a box

This example shows how to register a `Box` component. `'box'` is the value for `type`, which must
be unique, as Makeswift uses this value to identify the component. This value shouldn't change once you use the
component in the Makeswift builder. `'Box'` is the `label`, which appears in
the Makeswift builder. The example applies a [`Style`](/developer/docs/reference/controls/style) control to the
`className` prop.

**`makeswift/components.tsx`**

```tsx makeswift/components.tsx
import { Style } from "@makeswift/runtime/controls";

import { runtime } from "./runtime";

function Box({ className }) {
  return <div className={className}>I'm a box!</div>;
}

runtime.registerComponent(Box, {
  type: "box",
  label: "Box",
  props: {
    className: Style({ properties: Style.All }),
  },
});
```

### Creating sections

This example shows how to register a `Cube` and a `Sphere` component under a "Visuals" section. In each
components' `label`, use slashes to separate the section name and component name. In the Makeswift
builder, both components appear under the same Visuals collapsible section:

![Screenshot of registered component sections](/_fern-img/ebb52feddb10caf656d1fd51fcd334257f0bb296723c8ae60086de9f11230d11.webp)

**`makeswift/components.tsx`**

```tsx makeswift/components.tsx
import { Style } from "@makeswift/runtime/controls";

function Cube({ className }) {
  return <div className={className}>Cube!</div>;
}

function Sphere({ className }) {
  return <div className={className}>Sphere!</div>;
}

runtime.registerComponent(Cube, {
  type: "cube",
  label: "Visuals/Cube",
  props: {
    className: Style({ properties: Style.All }),
  },
});

runtime.registerComponent(Sphere, {
  type: "sphere",
  label: "Visuals/Sphere",
  props: {
    className: Style({ properties: Style.All }),
  },
});
```

### Overriding the built-in Suspense boundary

By default, the Makeswift runtime wraps registered components in a built-in `<Suspense>` boundary to
transparently enable efficient server-side streaming and asynchronous data fetching. If your component
already includes its own `<Suspense>` boundary, you can disable the built-in one by setting the
`builtinSuspense` option to `false`:

```tsx
import { TextInput } from "@makeswift/runtime/controls";
import { runtime } from "./runtime";

function Discography({ artistId }: { artistId?: string }) {
  return (
    <>
      <h2>Discography</h2>
      {/* component's own Suspense boundary with a fallback */}
      <Suspense fallback={<div>Loading...</div>}>
        <AlbumList artistId={artistId} />
      </Suspense>
    </>
  );
}

runtime.registerComponent(Discography, {
  type: 'section-discography',
  label: 'Discography',
  builtinSuspense: false, // disable the built-in Suspense boundary
  props: {
    artistId: TextInput({ label: 'Artist ID' }),
  },
});
```

### Assign an icon

This example shows how to register an `ImageGallery` component with a custom icon. Pass
the icon name as a string to the `icon` option.

> **Note**
>
> You can find all available icons in the [icons list](#icons-list) section.

In the builder
component tray, we can see our component with the selected icon.

![Screenshot of registered component icons](/_fern-img/260ed51d10840b035c2021e545f7d753e9e89870de04b8313fa2babd641267f8.webp)

**`makeswift/components.tsx`**

```tsx makeswift/components.tsx
import { Style } from "@makeswift/runtime/controls";

import { runtime } from "./runtime";

function ImageGallery({ className }) {
  return <div className={className}>I'm an image gallery!</div>;
}

runtime.registerComponent(ImageGallery, {
  type: "image-gallery",
  label: "ImageGallery",
  icon: "gallery",
  props: {
    className: Style({ properties: Style.All }),
  },
});
```

### Adding a description

This example shows how to add a `Circle` component with a rich description. We
can define a description string using markdown formatting, and pass it into the component description field.

```typescript
const mdDescription = `
# This is a larger heading

This is some text at the top of here

[![robot](https://plus.unsplash.com/premium_photo-1738614647383-0435fcb26a55?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxleHBsb3JlLWZlZWR8NHx8fGVufDB8fHx8fA%3D%3D)](https://www.youtube.com/watch?v=dQw4w9WgXcQ)

## This is a smaller heading

This is a **description** about this component, click to [learn more](https://www.youtube.com/watch?v=dQw4w9WgXcQ).
* First Item
* Second item

This is a line with some \`\`<code/>\`\`
`
```

**`makeswift/components.tsx`**

```tsx makeswift/components.tsx
import { Style } from "@makeswift/runtime/controls";

import { runtime } from "@/makeswift/runtime";

function Circle({ className }) {
  return <div className={className}>I'm a circle!</div>;
}

runtime.registerComponent(Circle, {
  type: "circle-tester",
  label: "Custom / Circle",
  icon: "chats",
  hidden: false,
  description: mdDescription,
  props: {
    className: Style({ properties: Style.All }),
  },
});
```

In the Properties Sidebar, we can see an info icon next to the component label. Hover over the label to open the description tooltip.

![custom component description open](/_fern-img/041fdb30f346f1a183ac57a99eb98cba3e526388cbf7c2a4023a353c624ddd11.webp)

Descriptions that are longer than the standard tooltip will have a scrollbar to view the overflowing content.

### Organizing registration code

As you register more components in `makeswift/components.tsx`, you may notice this file growing rather large. To keep your codebase organized, we recommend breaking out your Makeswift registration code into separate files and co-locating it with your component file.

For example, if you have a `Box` component, you can create a `Box.makeswift.ts` file next to your `Box.tsx` file. This file will contain the registration code for the `Box` component.

> **Info**
>
> Makeswift does **not** rely on this naming convention. Feel free to use
> whatever naming convention you prefer.

**`components/Box/Box.tsx`**

```tsx components/Box/Box.tsx
interface Props {
  className?: string;
}

function Box({ className }) {
  return <div className={className}>I'm a box!</div>;
}
```

**`components/Box/Box.makeswift.ts`**

```tsx components/Box/Box.makeswift.ts
import { Style } from "@makeswift/runtime/controls";

import { runtime } from "@/makeswift/runtime";

import { Box } from "./Box";

runtime.registerComponent(Box, {
  type: "box",
  label: "Box",
  props: {
    className: Style({ properties: Style.All }),
  },
});
```

Then update your `makeswift/components.tsx` file to import all of the component registrations, like so:

**`makeswift/components.ts`**

```ts makeswift/components.ts
import "@/components/Box/Box.makeswift";
import "@/components/Cube/Cube.makeswift";
import "@/components/Sphere/Sphere.makeswift";
import "@/components/Circle/Circle.makeswift";
/*
 * Add all of your component registrations here
 */
```

The file `makeswift/components.ts` should be imported wherever you use [`<ReactRuntimeProvider>`](/developer/docs/reference/components/react-runtime-provider) in your app.

## Icons List

Here is the list of available icons to use when registering your component.