Note: Studio is currently part of an Early Access Program and may not be available to all users. Contact the Contentstack support team; they will coordinate with the appropriate stakeholders to review eligibility.
Studio lets you style components directly from the Design tab in the canvas. You can apply styles using:
By understanding how to work with design tokens, responsive styles, classes, and component-level styling, you can create consistent, on-brand experiences while keeping code clean.
Note: You can add guardrails to restrict arbitrary values or design tokens using the registerDesignTokens() function.
When you select a component on the canvas and open the Design tab, you can:
Design tokens allow you to centralize your brand’s styles and apply them consistently across components.
Example: Registering a new token for sizes.
import { registerDesignTokens } from "@contentstack/studio-react";
registerDesignTokens({
size: {
height: {
L: "20rem",
},
width: {
XL: "30rem",
L: "10rem",
},
},
});
Tokens automatically appear in the Design tab when supported by a component’s style section.
Note: To enable token-based styling in your components, define style sections and pass corresponding class names. Refer to the Styling Your Registered Component section for more details.
Some tokens work across multiple style properties. For example:
You can also define compound tokens that group multiple design attributes:
Example: A “heading” style with font size, font family, and font weight:
{
typography: {
headingLarge: {
fontSize: "2rem",
fontWeight: 700,
fontFamily: "Inter, sans-serif",
},
},
}
Studio includes a built-in set of default design tokens.
Example: Update a Primary Color
import { registerDesignTokens } from "@contentstack/studio-react";
registerDesignTokens({
colorTokens: {
"color-primary": "#FF4171",
},
});
This will change the primary color from #6C5CE7 to #FF4171.
Example: Disable Default Tokens
registerDesignTokens({}, {
allowDefaultDesignTokens: false,
});
Studio supports responsive styling via CSS media queries. Use the Viewport Selector (top-right of canvas) to switch breakpoints visually.
Example: Register Breakpoints
import { registerBreakpoints } from "@contentstack/studio-react";
registerBreakpoints([
{
name: "default",
displayName: "All Screens",
previewSize: { width: 1200, height: 800 },
},
{
name: "tablet",
displayName: "Tablet",
query: "(max-width: 1023px)",
previewSize: { width: 800, height: 600 },
},
{
name: "mobile",
displayName: "Mobile",
query: "(max-width: 767px)",
previewSize: { width: 400, height: 500 },
},
]);
Note: The first breakpoint must be default. Styles without a matching media query will fall back to it.
Use predefined CSS classes for animations or non-tokenized styles.
Example: Register Custom Classes
import { registerDesignClasses } from "@contentstack/studio-react";
registerDesignClasses([
{
name: "better-heading",
displayName: "Better Heading",
},
]);
Registered classes are available in the Design tab under “Class Names.”
When registering a component, define style groups to expose style controls in the Design tab. These map to CSS class names that you can apply to elements in your component.
Example: Register Component with Style Groups
import { registerComponents } from "@contentstack/studio-react";
registerComponents({
name: "card",
displayName: "Card",
component: Card,
styles: {
default: {},
headerStyles: {},
bodyStyles: {},
footerStyles: {}
},
});
This allows the Design tab to show separate style sections: default, headerStyles, etc. In your registered component, you will get this as a prop that you must pass in the class name attribute of your component.
function Card({
className, headerStyles, bodyStyles, footerStyles
}: {
className: string,
headerStyles: string,
bodyStyles: string,
footerStyles: string
}) {
return (
<div classname="{className}">
<h3 classname="{headerStyles}">I am a header</h3>
<p classname="{bodyStyles}">I am a body</p>
<p classname="{footerStyles}">I am a footer</p>
</div>
);
}
This is how you can add styles to your registered component. As you can see, the default style group is passed against the className prop. This helps us support external components easily.
By default, the default style group is added to every registered component. Hence, you can pass the className prop directly to your component without adding anything in the registeredComponent function.
If you want no style groups, you can pass an empty object to the style property in the registeredComponent function.
registerComponents({
name: "card",
displayName: "Card",
component: Card,
styles: {},
});
By default, the key of the style group will appear in the Design tab. You can customize this name by passing an optional displayName property.
registerComponents({
name: "card",
displayName: "Card",
component: Card,
styles: {
default: { displayName: "Card" },
headerStyles: { displayName: "Header" },
bodyStyles: { displayName: "Body" },
footerStyles: { displayName: "Footer" }
},
});
You can limit which style controls appear in a style group:
registerComponents({
name: "card",
displayName: "Card",
component: Card,
styles: {
default: {
displayName: "Body",
styleSections: ["typography"], // Only typography controls shown
},
},
});
You can apply default tokens, classes, and static values to your components during registration. These styles will be applied to your default breakpoint when you drop the component in the canvas.
const classes = registerDesignClasses([
{ name: "better-heading", displayName: "Better Heading" },
] as const);
const tokens = registerDesignTokens(
{ colorTokens: { primary: "#ff0019" } } as const
);
registerComponents({
name: "card",
displayName: "Card",
component: Card,
styles: {
default: {
displayName: "Body",
defaultStyles: {
color: tokens.typography.color.primary,
backgroundColor: "white",
},
},
headerStyles: {
displayName: "Header",
defaultClasses: [classes["better-heading"]],
},
},
});
Tip: Mark token/class configs as const to enable autocomplete in your IDE.
Developers can control whether they want to allow arbitrary values in the design section. Additionally, they can limit which style controls appear in a style group.
import { registerDesignTokens } from "@contentstack/studio-react";
registerDesignTokens({}, {
allowedValuesLevel: "arbitrary", // Allows arbitrary and token values
});
Note: By default, only dynamic values are allowed. To enable design tokens or arbitrary values, you must configure registerDesignTokens().
registerComponents({
name: "card",
displayName: "Card",
component: Card,
styles: {
default: {
displayName: "Body",
styleSections: ["typography"], // Only typography controls shown
},
},
});
Styling in Studio gives you the flexibility to create visually rich, brand-consistent digital experiences, without sacrificing performance or developer control. By combining design tokens, responsive rules, and structured style groups, teams can collaborate efficiently while ensuring every component aligns with your design system. Whether you're working in the canvas or registering custom components, Studio’s styling framework scales with your needs, from rapid prototyping to enterprise-grade deployment.