Skip to main content

Built-in components

Look up the components Studio ships on the Components tab, what each one is for, and how to replace one with your own. Build your own components for your site's design, and use these to fill the gaps, such as a video or a raw HTML tag.

The example on this page is the team blog. Authors place Studio's Header and Paragraph next to your Avatar and Byline inside the Author card section.

You don't install or register them​

Studio's built-in components come with @contentstack/studio-react. Importing the package registers them, and so does rendering StudioCanvas or StudioComponent. You never call registerComponent for them.

They're on every project's Components tab, below the groups of components you register.

The 19 built-in components​

The Components tab sorts the tiles in each group A to Z. Use the type value, not the label, when you replace a built-in. Three labels differ from their type: Paragraph is text, Columns is hstack and Rows is vstack. There's no component called Heading. The heading component is Header.

LabeltypeKindGroupWhat it's for
ButtonbuttonAtomicBasicA button with a label and a link.
Collapsible Textcollapsible-textAtomicBasicText cut to a number of lines, with a button that expands it or opens a URL.
HeaderheaderAtomicBasicA heading, from h1 to h6.
LinklinkAtomicBasicA text link.
ParagraphtextAtomicBasicA paragraph of text.
Rich Textrich-textAtomicBasicFormatted text, such as the value of a rich text field.
Textplain-textAtomicBasicText with no element around it. It has no styles, so the Design tab can't style it.
EmbedembedAtomicMediaContent from another URL shown in a frame, such as a map or a video player.
ImageimageAtomicMediaAn image, with alt text.
VideovideoAtomicMediaA video file from a URL, with a poster image.
BoxboxLayoutContainerA container that holds other components.
ColumnshstackLayoutContainerSide-by-side columns. You set how many.
Link Containerlink-containerLayoutContainerA container that's a link, so everything in it is clickable.
RowsvstackLayoutContainerStacked rows. You set how many.
Condition Blockcondition-blockLayoutSmart ContainersShows its contents only when a condition is met. See Show or hide content with a condition.
RepeaterrepeaterLayoutSmart ContainersRepeats its contents once for each item in a list. See Render a list.
Section Slotsection-slotNeitherSmart ContainersMarks a place in a section that each template fills. See Section slots.
HTML Elementhtml-elementLayoutHTML ElementsAny HTML tag, with the attributes you set.
Style Sheetstyle-sheetNeitherHTML ElementsCSS you type, added to the composition.

The Kind column follows the split in Components, sections and templates. An atomic component has no slot and renders its own content, such as text, an image or a link. A layout component holds other components through a slot. Its own props are settings for the container, such as a link target. Kind isn't a Studio label, and the Components tab groups tiles by the Group column.

Two built-ins are neither kind. Section Slot is a placeholder with no slot of its own, and what the template drops in renders in its place. Style Sheet renders only a <style> tag, so nothing shows on the page.

Section Slot only appears while you're authoring a section​

A Section Slot marks a place in a section that each template using the section fills in. A template has nothing placed around it that could fill a slot, so Studio leaves Section Slot off the Components tab while you're working on a template. On the Blog post template you see 18 built-in components. Open the Author card section and Section Slot is there.

How slots are filled is in Section slots.

Replace a built-in with your own​

To make a built-in render your own component, register yours with the built-in's type and pass overrideDefaultComponents: true. Without it, Studio skips your registration and keeps the built-in, with no message.

The blog replaces Button with its own BlogButton.

// src/components/BlogButton.tsx
import type { StudioAttributes } from "@contentstack/studio-react";

type BlogButtonProps = StudioAttributes & {
label: string;
link: string;
openInNewTab: boolean;
};

export function BlogButton({ label, link, openInNewTab, studioAttributes }: BlogButtonProps) {
return (
<a
{...studioAttributes}
className="blog-button"
href={link}
target={openInNewTab ? "_blank" : undefined}
rel={openInNewTab ? "noopener noreferrer" : undefined}
>
{label}
</a>
);
}
import { registerComponents } from "@contentstack/studio-react";
import { BlogButton } from "./components/BlogButton";

registerComponents(
[
{
type: "button",
component: BlogButton,
displayName: "Button",
wrap: false,
sections: "Basic",
props: {
label: { type: "string", displayName: "Label", defaultValue: "Button" },
link: { type: "href", displayName: "Link" },
openInNewTab: { type: "boolean", displayName: "Open in New Tab", defaultValue: false },
},
},
],
{ overrideDefaultComponents: true },
);

What changes:

  • Every Button already placed in your templates and sections renders BlogButton instead.
  • Only the props you declare reach it. The built-in Button's props are label, link and openInNewTab. Declare the same names to keep the values authors already set.
  • The tile moves to Registered Components unless you set sections. The example puts it back in Basic.
  • The tile loses the built-in's icon. It shows your thumbnail, or a default one. See Group components and add thumbnails.

overrideDefaultComponents stays on for every later registration, so a later component with a type that's already registered replaces that one too.

You can't replace page. It's a system component, so registering that type throws an error.

If it doesn't work​

Section Slot isn't on the Components tab​

You're working on a template. Open the section you want the slot in, such as Author card. See Section slots.

Your component doesn't replace the built-in​

You registered a built-in's type without overrideDefaultComponents: true, so Studio kept the built-in. If you also passed strict: true, registration throws instead:

Component with type 'button' is already registered.

Registering type: "page" always throws:

Component with type 'page' is a system component and cannot be overridden.

A fetch fails because Studio's own components are missing​

The fetch fails with an error whose message starts like this, naming the built-ins it couldn't find. sdk.fetchCompositionData throws it, and useCompositionData returns it as error. The SDK doesn't log it, so you see it where your app logs or shows that error.

[Contentstack Studio] COMPONENT_NOT_REGISTERED: Studio's own components are not registered: repeater.

The package root was never imported, so the built-ins never registered. Add import "@contentstack/studio-react"; once, before you fetch. See COMPONENT_NOT_REGISTERED.

Where to go next​

Report a problem with this page