---
title: "React Studio SDK API Reference"
description: "Implement Contentstack Studio SDK using React Hooks, component registration, JSON RTE, and design tokens for consistent UI composition, rendering, and integration setup."
url: "https://www.contentstack.com/docs/developers/sdks/studio-sdk/react/reference"
product: "Contentstack"
doc_type: "guide"
audience:
  - developers
  - admins
version: "current"
last_updated: "2025-10-31"
---

# React Studio SDK API Reference

## React Studio SDK API Reference

The Studio React SDK lets developers integrate and render Contentstack Studio compositions within React applications. It connects the application to Contentstack’s Delivery SDK, enabling Live Preview and synchronization between Studio and the deployed front end.  
  
The SDK supports initializing Studio, loading compositions, and rendering structured layouts in React. It also includes utilities to manage component registration, design tokens, responsive breakpoints, and Studio-level interactions for building modular and composable front-end experiences.

**Additional Resources:**

To learn more about Studio and its integration, refer to our [About Studio](/docs/developers/sdks/studio-sdk/react/about-studio-react-sdk) and [Get Started with Studio React SDK](/docs/developers/sdks/studio-sdk/react/get-started-with-studio-react-sdk) documents.

## Hooks

Contentstack provides a set of custom React Hooks that align with standard React patterns. These Hooks help developers access the data and context needed to manage component behavior and data flow effectively.

## useCompositionData

The useCompositionData React hook fetches composition data and specifications. Use this as the primary method to load a composition along with its SEO and meta information.

## Options

The following options let you customize how the SDK fetches composition data.

Name

Type

Description

variantAlias

string

Identifies a CMS variant created by Contentstack Personalize. You can pass the alias to the Delivery API or Delivery SDK to fetch personalized content. Use this instead of the variant UID in API and SDK requests. 

extendQuery

object

Controls which reference fields and entry fields are fetched per content type. Use this when you need additional references (for example, inside arrays or modular blocks) or extra entry fields that are not bound in the composition.

## variantAlias

When you pass variantAlias, the SDK includes it in the request so the Delivery API returns data for the specified variant.

A variant alias typically looks like cs\_personalize\_a\_0, where:

*   cs\_personalize is the prefix for Personalize-created variants.
*   The remaining segments identify the experience and the activated variant.

**Example**:

useCompositionData(
  { compositionUid: "home-page", url: "/home" },
  { variantAlias: "cs\_personalize\_a\_0" }
);

## extendQuery

extendQuery is an optional configuration under CompositionQueryOptions. It lets you control:

*   Which reference fields are included
*   Which entry fields are fetched for each content type

By default, the SDK fetches only the entry fields that are bound in the composition. Use extendQuery when you need:

*   Additional references (for example, references inside arrays or modular blocks)
*   Additional entry fields that are not bound in the composition

extendQuery supports two optional properties:

*   includeReferences
*   only

## includeReferences

The includeReferences works the same way as the [Delivery SDK’s](/docs/developers/sdks/content-delivery-sdk/typescript/reference#includereference) includeReferences option. It retrieves the content of referenced entries in the response.

Use this option to include reference fields that are not already implied by the composition’s bindings.

## only

The only works the same way as the [Delivery SDK’s](/docs/developers/sdks/content-delivery-sdk/typescript/reference#only) only query parameter. It lets you select specific fields of an entry.

By default, only bound entry fields are fetched. Use only to include additional entry fields (field UIDs) that are not bound in the composition.

**Example 1**:

useCompositionData(
  { compositionUid: "home-page", url: "/home" },
  {
    extendQuery: {
      page: {
        includeReferences: \["hero\_image", "sections.author"\],
        only: \["title", "url", \["hero\_image", "url"\], \["sections.author", "name"\]\],
      },
    },
  }
);

**Example 2**:

const options = {
  variantAlias: "cs\_personalize\_a\_0",
  extendQuery: {
    page: {
      includeReferences: \["hero\_image"\],
      only: \["title", "url", \["hero\_image", "url"\]\],
    },
  },
};

// fetchCompositionData(for SSR)
const specOptions = await studioSdk.fetchCompositionData(
  { compositionUid: "home-page", searchQuery },
  options
);

// useCompositionData
const { specOptions, isLoading, error } = useCompositionData(
  { compositionUid: "home-page", url: "/home" },
  options
);

## useSelected

The useSelected React hook identifies whether the current component instance is selected within Studio. This is useful for displaying inline tooltips, dialogs, or other contextual UI elements.

## useHiddenElementNotification

The useHiddenElementNotification React hook enables components to show or hide modals, tooltips, dialogs, or other hidden elements that require external control. It notifies Studio when the component should be opened for editing.

**When to Use**

*   **Modals/Dialogs:** When you need to show or hide modal content.
*   **Tooltips:** For displaying contextual information.
*   **Dropdowns:** For expandable content sections.
*   **Hidden Sections:** For collapsible content areas.
*   **Any Interactive Element:** That needs to be controlled from outside the canvas.

**Note:** When using this hook, register the component in registerComponents with wrap: false. The component will receive a studioAttributes prop. Destructure it to ensure proper behavior, and expose open and close via useImperativeHandle.

## Utilities

Contentstack’s SDK provides utilities that help developers detect page and component states, such as loading or selection. These utilities determine how components render and behave, ensuring consistent and predictable interactions across the application.

## clientRendererModeUtil

The clientRendererModeUtilutility determines the renderer mode and environment. It provides methods to check the current rendering context and adjust component behavior accordingly.

## isInsideStudioFrame

The isInsideStudioFrame() method checks whether the app is running inside Studio to adapt its behavior specifically for the Studio environment.

**Note:** Use this method to enable Studio-specific behavior only when the application runs inside Studio.

## isInsideIframe

The isInsideIframe() method checks whether the app is running inside an iframe, which can affect rendering and communication with parent contexts.

**Note:** Implement cross-frame communication or adjust the UI when running inside an iframe.

## isInsideVisualBuilderFrame()

The isInsideVisualBuilderFrame() method checks whether the app is running inside the Visual Builder frame, which provides additional editing capabilities.

**Note:** Enable enhanced editing features when in the Visual Builder environment.

## isEditingCurrentComposition

The isEditingCurrentComposition() method verifies whether a specific composition, identified by its UID, is currently being edited. This ensures that interactive or editable features activate only when the targeted composition is in edit mode.

Use this method when multiple compositions are displayed on a single page and you need to identify which one is currently active for editing.

## getMode

The getMode() method determines the current renderer mode for a given composition, identified by its UID. It allows components to conditionally render UI elements based on whether the composition is in edit, edit-button, or preview mode.

## Component Registry

## registerComponents

The registerComponents method registers custom React components in Studio, making them available in the Visual Builder and Studio interface. This is the primary method for integrating reusable UI components into the composition workflow.

## Component Configuration Options

**Parameter**

**Type**

**Description**

type (required)

string

Unique identifier for the component. Used internally.

component (required)

React.Component

The React component to register. Can be a function or class component.

wrap

boolean | string

Controls whether the component is wrapped in a container element.

*   true (default): Wrapped in a <div>.
*   false: Not wrapped (useful when handling your own container).
*   string: Wrapped in the specified HTML tag (e.g., section, span).

displayName

string

Name shown in the component library. Defaults to type if not specified.

description

string

Description shown in the component library for authors.

sections

string\[\] | string

Determines where the component appears in the left panel. Built-in sections include:

*   Basic: Text, buttons, links
*   Media: Images, video, embed
*   Container: Section, box, columns
*   Smart Containers: Repeaters, condition blocks
*   Advanced: Tabs, modals, accordions
*   Custom Components: User-defined

thumbnailUrl

string

Thumbnail image displayed in the component library.

props

object

Defines configurable props (see below).

styles

object

Defines style groups, default classes, and available style sections.

  

**Note:** When using useHiddenElementNotification, set wrap: false and destructure the studioAttributes prop in your component.

## Props Configuration

The props object defines configurable properties for your component, with each prop offering options that enhance the editing experience in Studio.

Common prop options include:

*   type: Data type of the prop (required).
*   displayName: Label shown in the editor.
*   defaultValue: Initial value when the component is first added.
*   helpText: Helper text to guide content creators.

**Supported Prop Types**

*   **String Prop** ("string")
    
    The string prop defines a text input field for capturing short to long text content.
    
    **Options**
    
    *   control: "default" (single-line), "large" (multi-line textarea), "markdown" (markdown editor)
    *   placeholder: Hint text when empty.
    *   defaultValue: Initial text value.
    *   helpText: Guidance for authors.

**Use Cases:** Titles, descriptions, names, URLs, or custom text fields.

**Example**

*   **Boolean Prop** ("boolean")
    
    The boolean prop defines a toggle switch for capturing true or false values.
    
    **Options**
    
    *   defaultValue: Initial state (true or false).
    *   helpText: Guidance for authors.

**Use Cases:** Show/hide elements, enable/disable features, toggle states.

**Example**

showHeader: {
  type: "boolean",
  displayName: "Show Header",
  defaultValue: true,
  helpText: "Toggle the visibility of the page header"
}

*   **Number Prop** ("number")
    
    The number prop defines a numeric input field for capturing integers and decimal values.
    
    **Options**
    
    *   defaultValue: Initial numeric value.
    *   helpText: Guidance for authors.
    *   control: "default" (number field) or "slider" (number slider).
    *   max: The maximum allowed value.
    *   min: The minimum allowed value.
    *   step: The increment or decrement step size when adjusting the value.

**Use Cases:** Counts, dimensions, ratings, percentages, or quantity limits.

**Example**

maxItems: {
  type: "number",
  displayName: "Maximum Items",
  defaultValue: 10,
  helpText: "Maximum number of items to display"
}

*   **Choice Prop** ("choice")
    
    The choice prop defines a selection input from a predefined list of options.
    
    **Options**
    
    *   options: An array of available options.
    *   defaultValue: Selected option(s) (must be an array).
    *   multiSelect: Controls whether multiple values can be selected.
    *   control: "radio" or "dropdown".

**Use Cases:** Variants, themes, sizes, categories, or status fields.

**Example**

buttonStyle: {
  type: "choice",
  displayName: "Button Style",
  options: \["primary", "secondary", "outline", "ghost"\],
  defaultValue: \["primary"\],
  control: "radio",
  helpText: "Choose the visual style of the button"
}

*   **Date String Prop** ("datestring")
    
    The datestring prop defines a picker input for selecting date and time values.
    
    **Options**
    
    *   defaultValue: ISO date string.
    *   helpText: Guidance for authors.

**Use Cases:** Publication dates, event dates, expirations, or timestamps.

**Example**

publishDate: {
  type: "datestring",
  displayName: "Publication Date",
  defaultValue: new Date().toISOString(),
  helpText: "When this content should be published"
}

*   **Href Prop** ("href")
    
    The href prop defines a URL input field for navigation and linking purposes.
    
    **Options**
    
    *   defaultValue: Initial URL value.
    *   helpText: Guidance for authors.

**Use Cases:** Navigation links, external resources, or internal routing.

**Example**

learnMoreUrl: {
  type: "href",
  displayName: "Learn More Link",
  defaultValue: "https://example.com/learn-more",
  helpText: "URL for the learn more page"
}

*   **Image URL Prop** ("imageurl")
    
    The imageurl prop defines a specialized URL input field for specifying image sources.
    
    **Options**
    
    *   defaultValue: Initial image URL.
    *   helpText: Guidance for authors.

**Use Cases:** Image sources, backgrounds, banners, or icons.

**Example**

heroImage: {
  type: "imageurl",
  displayName: "Hero Image",
  defaultValue: "https://example.com/hero.jpg",
  helpText: "Main image for the hero section"
}

*   **Object Prop** ("object")
    
    The object prop defines a nested configuration object based on a custom schema.
    
    **Options**
    
    *   defaultValue: Initial object.
    *   properties: Schema definition for the object’s structure.

**Use Cases:** Theme settings, configuration objects, or grouped options.

**Example**

themeSettings: {
  type: "object",
  displayName: "Theme Settings",
  defaultValue: {
    color: "blue",
    fontSize: "16px"
  },
  properties: {
    color: {
      type: "string",
      displayName: "Primary Color"
    },
    fontSize: {
      type: "string",
      displayName: "Font Size"
    }
  }
}

* * *

*   **Array Prop** ("array")
    
    The array prop defines a collection of values or objects.
    
    **Options**
    
    *   defaultValue: Initial array.
    *   items: Defines the schema of each item in the array.
    *   helpText: Guidance for authors.

**Use Cases:** Lists, tags, categories, or repeated items.

**Example**

tagList: {
  type: "array",
  displayName: "Tags",
  items: {
    type: "string"
  },
  defaultValue: \["1", "2", "3"\]
}

*   **Slot Prop** ("slot")
    
    The slot prop defines a container placeholder for child components or dynamic content.
    
    **Options**
    
    *   displayName: Label shown in the editor.
    *   helpText: Guidance for authors.

**Use Cases:** Flexible layouts, drag-and-drop child components.

**Example**

mainSlot: {
  type: "slot",
  displayName: "Main Slot",
  helpText: "Container for nested components"
}

* * *

*   **JSON RTE Prop** ("json\_rte")
    
    The json\_rte prop defines a Rich Text Editor field for structured and formatted content.
    
    **Options**
    
    *   defaultValue: JSON document structure.
    *   helpText: Guidance for authors.

**Use Cases:** Formatted text, complex content blocks, long-form descriptions.

**Example**

content: {
  type: "json\_rte",
  displayName: "Main Content",
  defaultValue: {
    type: "doc",
    content: \[
      {
        type: "paragraph",
        content: \[{ type: "text", text: "Enter your content here..." }\]
      }
    \]
  },
  helpText: "Rich text content with formatting options"
}

*   **Any Prop** ("any")
    
    The any prop defines a flexible data type for dynamic or miscellaneous content. When you mark a prop as any, you can link any data to the field from Contentstack.
    
    **Options**
    
    *   defaultValue: Initial value (any type).
    *   helpText: Guidance for authors.

**Use Cases:** Custom data, experimental fields, or dynamic inputs not covered by other prop types.

**Example**

customData: {
  type: "any",
  displayName: "Custom Data",
  defaultValue: null,
  helpText: "Store any additional data for this component"
}

## Options Configuration

*   **allowedBuiltInComponents**
    
    The allowedBuiltInComponents option controls the built-in components available in the registry.
    
    **Type:** boolean | string\[\]
    
    **Values**
    
    *   true (default): Enable all built-in components.
    *   false: Disable all built-in components.
    *   string\[\]: Enable specific built-in components.
    
    **Built-in Component Categories**
    
    *   **Basic Components:** page, symbol, fragment, text, header, button, link, link-container, json-rte, collapsible-text.
    *   **Media Components:** video, embed, image.
    *   **Container Components:** section, box, hstack (columns), vstack (rows), repeater, condition-block.
    
    **Example**
    
    // Enable all built-in components
    registerComponents(components, {
      allowedBuiltInComponents: true
    });
    
    // Disable all built-in components
    registerComponents(components, {
      allowedBuiltInComponents: false
    });
    
    // Enable only specific built-in components
    registerComponents(components, {
      allowedBuiltInComponents: \[
        "button",
        "text",
        "image",
        "section",
        "box"
      \]
    });
    
*   **overrideDefaultComponents**
    
    The overrideDefaultComponents option controls whether user components can override built-in components with the same type name.
    
    **Type:** boolean
    
    **Values**
    
    *   false (default): Built-in components cannot be overridden.
    *   true: User components can override built-in components.

**Example**

// Allow overriding built-in components
registerComponents(components, {
  overrideDefaultComponents: true
});

// Prevent overriding (safer option)
registerComponents(components, {
  overrideDefaultComponents: false
});

**Error Handling**

When overrideDefaultComponents is false, attempting to register a component with the same type as a built-in component will throw an error:

try {
  registerComponents(
    \[
      {
        type: "button", // This conflicts with built-in button
        component: CustomButton
      }
    \],
    {
      overrideDefaultComponents: false
    }
  );
} catch (error) {
  // Error: "Component with type 'button' is already registered."
  console.error("Registration failed:", error.message);
}

## JSON RTE Registry

## registerJsonRte

The registerJsonRte method registers custom element types (blocks) and text wrappers (inline marks) for JSON RTE content.

**Use Case:** Extend the default rich-text rendering with branded components, custom formatting, and visual effects.

**Parameters:**

**Name**

**Type**

**Description**

config

IJsonToHtmlOptions

Configuration object for custom JSON RTE rendering.

  

import { registerJsonRte } from '@contentstack/studio-react';

registerJsonRte({
  customElementTypes: {
    // Custom block-level elements
    infoBox: (attrs, child, jsonBlock, extraProps) => {
      return \`<div class="info-box" style="padding: 1rem; background-color: #e3f2fd; border-left: 4px solid #2196f3;">${child}</div>\`;
    },
    callout: (attrs, child, jsonBlock, extraProps) => {
      const type = jsonBlock.attrs?.type || 'info';
      const colors = {
        info: '#e3f2fd',
        warning: '#fff3e0',
        error: '#ffebee',
        success: '#e8f5e9'
      };
      return \`<div class="callout callout-${type}" style="padding: 1rem; background-color: ${colors\[type\]}; border-radius: 4px; margin: 1rem 0;">${child}</div>\`;
    }
  },

  customTextWrapper: {
    // Custom inline text formatting
    highlight: (child, value) => {
      return \`<span class="highlight" style="background-color: #ffeb3b; padding: 2px 4px;">${child}</span>\`;
    },
    color: (child, value) => {
      return \`<span class="text-color" style="color: ${value};">${child}</span>\`;
    },
    code: (child, value) => {
      return \`<code class="inline-code" style="background-color: #f5f5f5; padding: 2px 4px; border-radius: 3px; font-family: monospace;">${child}</code>\`;
    }
  },

  allowNonStandardTypes: true
});

## Configuration Options

The configuration options let developers control how JSON RTE content is converted to HTML. You can define custom elements, text wrappers, and allow non-standard types to extend rendering behavior.

#### customElementTypes (IJsonToHtmlElementTags)

The customElementTypes option defines the block-level elements you want to support in rich text.

**Function Signature**

**Parameters**

**Name**

**Type**

**Description**

attrs

string

HTML attributes represented as a string.

child

string

The rendered inner HTML content of the element.

jsonBlock

object

The full JSON block object. Use jsonBlock.attrs to access attributes.

extraProps

object (optional)

Additional context props passed from the rendering environment.

customElementTypes: {
  // Custom info box component
  infoBox: (attrs, child, jsonBlock) => {
    const title = jsonBlock.attrs?.title || 'Information';
    const icon = jsonBlock.attrs?.icon || 'ℹ️';
    return \`
<div class="info-box" style="border: 1px solid #ddd; border-radius: 8px; padding: 1rem; margin: 1rem 0;">
  <div style="display: flex; align-items: center; margin-bottom: 0.5rem;">
    <span style="font-size: 1.2rem; margin-right: 0.5rem;">${icon}</span>
    <strong>${title}</strong>
  </div>
  <div>${child}</div>
</div>
\`;
  },

  // Custom quote component
  quote: (attrs, child, jsonBlock) => {
    const author = jsonBlock.attrs?.author || 'Unknown';
    const source = jsonBlock.attrs?.source || '';
    return \`
<blockquote class="custom-quote" style="border-left: 4px solid #007bff; padding-left: 1rem; margin: 1rem 0; font-style: italic;">
  <div>${child}</div>
  <footer style="margin-top: 0.5rem; font-size: 0.9rem; color: #666;">
    — ${author}${source ? \`, ${source}\` : ''}
  </footer>
</blockquote>
\`;
  }
}

#### customTextWrapper (IJsonToHtmlTextTags)

The customTextWrapper option defines inline text wrappers or marks used for applying formatting and effects to text within JSON RTE content.

**Use Case:** Enables custom styles such as highlights, keyboard inputs, or branded inline elements in rich-text fields.

**Function Signature**

(child: any, value: any) => string

**Parameters**

**Name**

**Type**

**Description**

child

string

The text content to wrap.

value

any

The attribute value applied to the wrapper (for example, a color code, style, or effect).

**Example**

customTextWrapper: {
  // Highlight text with custom colors
  highlight: (child, value) => {
    const colors = {
      yellow: '#ffeb3b',
      green: '#4caf50',
      blue: '#2196f3',
      red: '#f44336'
    };
    const color = colors\[value\] || value;
    return \`<span class="highlight" style="background-color: ${color}; padding: 2px 4px; border-radius: 3px;">${child}</span>\`;
  },

  // Custom text styling
  style: (child, value) => {
    const styles = {
      bold: 'font-weight: bold;',
      italic: 'font-style: italic;',
      underline: 'text-decoration: underline;',
      strikethrough: 'text-decoration: line-through;'
    };
    const style = styles\[value\] || '';
    return \`<span style="${style}">${child}</span>\`;
  },

  // Custom font sizes
  fontSize: (child, value) => {
    return \`<span style="font-size: ${value}px;">${child}</span>\`;
  }
}

#### allowNonStandardTypes (boolean)

The allowNonStandardTypes option enables the use of non-standard element types in JSON RTE content.

**Use Case:**

*   **Custom Components:** Add branded elements such as info boxes, callouts, or product cards.
*   **Enhanced Text:** Format text with highlights, colors, or special fonts.
*   **Interactive Elements:** Insert interactive components, like buttons or widgets, into rich text.
*   **Brand Consistency:** Ensure rich text content aligns with your design system and styling standards.

  

**Real World Example**

import { registerJsonRte } from '@contentstack/studio-react';

// Register custom JSON RTE components for a marketing website
registerJsonRte({
  customElementTypes: {
    // Product showcase within rich text
    productShowcase: (attrs, child, jsonBlock) => {
      const product = jsonBlock.attrs;
      return \`
<div class="product-showcase" style="
  border: 2px solid #e0e0e0;
  border-radius: 12px;
  padding: 1.5rem;
  margin: 1.5rem 0;
  background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
">
  <div style="display: flex; align-items: center; gap: 1rem;">
    <img src="${product.image || '/placeholder.jpg'}"
      alt="${product.name || 'Product'}"
      style="width: 80px; height: 80px; border-radius: 8px; object-fit: cover;">
    <div>
      <h4 style="margin: 0 0 0.5rem 0; color: #2c3e50;">${product.name || 'Product Name'}</h4>
      <p style="margin: 0 0 0.5rem 0; color: #7f8c8d;">${product.description || 'Product description'}</p>
      <div style="font-size: 1.25rem; font-weight: bold; color: #e74c3c;">
        $${product.price || '0.00'}
      </div>
    </div>
  </div>
  ${child}
</div>
\`;
    },

    // Testimonial block
    testimonial: (attrs, child, jsonBlock) => {
      const testimonial = jsonBlock.attrs;
      return \`
<div class="testimonial" style="
  background-color: #f8f9fa;
  border-left: 4px solid #007bff;
  padding: 1.5rem;
  margin: 1.5rem 0;
  border-radius: 0 8px 8px 0;
">
  <div style="font-style: italic; margin-bottom: 1rem; color: #495057;">
    "${child}"
  </div>
  <div style="display: flex; align-items: center; gap: 0.5rem;">
    <img src="${testimonial.avatar || '/default-avatar.jpg'}"
      alt="${testimonial.author || 'Author'}"
      style="width: 40px; height: 40px; border-radius: 50%; object-fit: cover;">
    <div>
      <strong style="color: #2c3e50;">${testimonial.author || 'Author Name'}</strong>
      ${testimonial.title ? \`<br><span style="color: #6c757d; font-size: 0.9rem;">${testimonial.title}</span>\` : ''}
    </div>
  </div>
</div>
\`;
    },

    // Code block with syntax highlighting
    codeBlock: (attrs, child, jsonBlock) => {
      const language = jsonBlock.attrs?.language || 'text';
      return \`
<div class="code-block" style="
  background-color: #2d3748;
  border-radius: 8px;
  padding: 1rem;
  margin: 1rem 0;
  overflow-x: auto;
">
  <div style="
    color: #e2e8f0;
    font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
    font-size: 0.9rem;
    line-height: 1.5;
  ">
    <div style="
      color: #a0aec0;
      border-bottom: 1px solid #4a5568;
      padding-bottom: 0.5rem;
      margin-bottom: 1rem;
      font-size: 0.8rem;
      text-transform: uppercase;
      letter-spacing: 0.05em;
    ">
      ${language}
    </div>
    <pre style="margin: 0; white-space: pre-wrap;">${child}</pre>
  </div>
</div>
\`;
    }
  },

  customTextWrapper: {
    // Brand colors for text
    brandColor: (child, value) => {
      const brandColors = {
        primary: '#007bff',
        secondary: '#6c757d',
        success: '#28a745',
        danger: '#dc3545',
        warning: '#ffc107',
        info: '#17a2b8'
      };
      const color = brandColors\[value\] || value;
      return \`<span style="color: ${color}; font-weight: 500;">${child}</span>\`;
    },

    // Custom text effects
    textEffect: (child, value) => {
      const effects = {
        glow: 'text-shadow: 0 0 10px currentColor;',
        shadow: 'text-shadow: 2px 2px 4px rgba(0,0,0,0.3);',
        outline: 'text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000;'
      };
      const effect = effects\[value\] || '';
      return \`<span style="${effect}">${child}</span>\`;
    }
  },

  allowNonStandardTypes: true
});

## Conditional Props

Conditional props are component props whose values depend on the values of other props. They enable components to change behavior or configuration dynamically, based on user selections or predefined logic.

**Use Case:** Show or modify a prop’s value only when another related prop meets a certain condition — for example, displaying a "link URL" field only when "link enabled" is set to true.

**Example**

props: {
  showAdvanced: {
    type: "boolean",
    displayName: "Show Advanced Options",
    defaultValue: false
  },
  advancedConfig: {
    type: "object",
    displayName: "Advanced Configuration",
    defaultValue: {},
    // This prop will only be shown when showAdvanced is true
    // (handled automatically by the Studio)
  }
}

## Binding Support

Binding Support allows all component props to connect to external data sources using data binding.

**Use Case:** Dynamically populate component values  such as text, images, or links  by binding them to CMS entries, API responses, or environment variables within Studio.

## Styles Configuration

The styles object defines the styling options available for your component, enabling customization of its visual appearance.

**Example**

styles: {
  // Default style group
  default: {
    styleSections: \["size", "spacing", "background", "border"\],
    defaultClasses: \["my-component", "rounded"\],
    defaultStyles: { padding: "1rem" },
    displayName: "Default Styles"
  },

  // Custom style group
  custom: {
    styleSections: \["typography", "transform"\],
    defaultClasses: \["custom-text"\],
    defaultStyles: { fontSize: "16px" },
    displayName: "Custom Styles"
  }
}

  

**Available Style Sections**

**Section**

**Description**

class

Custom CSS classes.

size

Width, height, min/max dimensions.

spacing

Margin and padding.

position

Position and z-index.

visibility

Display and opacity.

layout

Flexbox and grid properties.

typography

Font properties and text alignment.

transform

Transform properties.

media

Media query styles.

background

Background properties.

shadow

Box and text shadow.

effect

Filter and backdrop-filter.

overflow

Overflow properties.

border

Border properties.

responsive

Responsive design utilities.

  

**Style Section Categories**

**Category**

**Description**

block

All block-level styling options.

text

Typography-focused styling options.

## Registry Options

The registerComponents configuration object controls built-in component availability, user overrides, and debug logging behavior.

#### allowedBuiltInComponents

The allowedBuiltInComponents option controls the built-in components available in the registry.

**Type:** boolean | string\[\]

**Values:**

*   true: Enable all built-ins (default)
*   false: Disable all built-ins
*   string\[\]: Enable only specific built-in types

#### overrideDefaultComponents

The overrideDefaultComponents option determines if user components override built-in components with the same type identifier.

**Type:** boolean

**Values:**

*   false: Prevent overriding built-ins (default)
*   true: Allow user components to override

#### debug

The debug option enables debug logging for troubleshooting during component registration.

**Type:** boolean

**Values:**

*   false: Disable logging (default)
*   true: Enable logging

#### Usage Example

// Basic component registration
registerComponents(\[
  {
    type: "hero-section",
    component: HeroSection,
    displayName: "Hero Section",
    description: "A prominent section for main content",
    sections: \["Custom Components"\]
  }
\]);

// Advanced component with full configuration
registerComponents(\[
  {
    type: "product-card",
    component: ProductCard,
    displayName: "Product Card",
    description: "Display product information in a card format",
    sections: \["Custom Components", "E-commerce"\],
    wrap: false,
    thumbnailUrl: "/images/product-card-thumbnail.png",
    hideFromContentCreators: false,
    hideFromComponentList: false,
    props: {
      productId: {
        type: "string",
        displayName: "Product ID",
        placeholder: "Enter product ID"
      },
      showPrice: {
        type: "boolean",
        displayName: "Show Price",
        defaultValue: true
      }
    },
    styles: {
      default: {
        styleSections: \["size", "spacing", "background", "border"\],
        defaultClasses: \["product-card"\],
        displayName: "Card Styles"
      },
      content: {
        styleSections: \["typography"\],
        defaultClasses: \["product-content"\],
        displayName: "Content Styles"
      }
    }
  }
\]);

// Component with validation
registerComponents(\[
  {
    type: "contact-form",
    component: ContactForm,
    displayName: "Contact Form",
    description: "A form for collecting contact information",
    sections: \["Forms"\],
    props: {
      email: {
        type: "string",
        displayName: "Email",
        placeholder: "Enter email address"
      }
    }
  }
\]);

## registerComponents

The registerComponents method makes custom React components available in Studio. Once registered, these components can be added, configured, and styled by content creators within the Studio interface alongside built-in components.

**Returns**

Type void

**Parameters**

**Name**

**Type**

**Description**

componentConfig (required)

Component configuration object

One or more component configurations to register.

options

Optional registry configuration

Controls built-ins, overrides, and debugging.

**Example**

import { registerComponents } from '@contentstack/studio-react';

registerComponents(componentConfig, options);

## Best Practices

*   **Performance:** Keep custom element renders lightweight and avoid complex DOM manipulation.
*   **Accessibility:** Use semantic HTML and include appropriate ARIA attributes to ensure custom elements are usable with assistive technologies.
*   **Responsiveness:** Apply CSS and layout techniques that adapt well across devices.
*   **Consistency:** Align custom elements with your design system to maintain a cohesive appearance across content.
*   **Testing:** Validate custom elements with varied content scenarios, edge cases, and real-world usage to ensure stability and reliability.

**Note:**

*   **Unique type:** Each component requires a unique identifier.
*   **System protection:** Built-in components cannot be overridden.
*   **Validation:** Props can include custom validation rules.
*   **Styling:** Components have access to design tokens and CSS-in-JS.
*   **Interactivity:** Use useHiddenElementNotification with wrap: false for interactive components.
*   **Performance:** Components are registered once and cached for efficiency.

## Design Registry

The Design Registry manages shared, reusable styling primitives for your project. It centralizes **design tokens** and **design classes** to deliver consistent styling across components. It supports validation and automatic exposure of tokens as CSS custom properties on :root.

## registerDesignTokens

The registerDesignTokens method registers design tokens and exposes them as CSS variables. These tokens define consistent visual attributes such as color palettes, spacing scales, and typography settings across components and interfaces.

  

**Parameters**

**Name**

**Type**

**Description**

designTokens (required)

DesignTokensInput

Object containing your token groups and values.

options

Partial<DesignTokensOptionsInput>

Optional configuration object for advanced token registration behavior.

**Returns**

Type      DesignTokens

A normalized object reflecting the registered token groups and their corresponding CSS variables.

Below is an outline of supported tokens:

#### Tokens Configuration

Below is an outline of supported tokens:

##### Global Tokens

Global tokens define high-level, project-wide primitives that serve as foundational values for other token categories.

**Example**

{
  colorTokens: {
    primary: "#007bff",
    secondary: "#6c757d",
    success: "#28a745",
    danger: "#dc3545",
    warning: "#ffc107",
    info: "#17a2b8"
  },
  spaceTokens: {
    xs: "0.25rem",
    sm: "0.5rem",
    md: "1rem",
    lg: "1.5rem",
    xl: "3rem"
  }
}

##### Size Tokens

Size tokens define base sizing primitives and common dimensional presets for consistent layout and spacing.

**Example**

{
  size: {
    tokens: {
      xs: "4px",
      sm: "8px",
      md: "16px",
      lg: "32px",
      xl: "64px"
    },
    width: {
      "w-full": "100%",
      "w-auto": "auto",
      "w-screen": "100vw"
    },
    height: {
      "h-full": "100%",
      "h-auto": "auto",
      "h-screen": "100vh"
    },
    minWidth: {
      "min-w-0": "0px",
      "min-w-full": "100%"
    },
    minHeight: {
      "min-h-0": "0px",
      "min-h-full": "100%"
    },
    maxWidth: {
      "max-w-xs": "20rem",
      "max-w-sm": "24rem",
      "max-w-md": "28rem"
    },
    maxHeight: {
      "max-h-32": "8rem",
      "max-h-64": "16rem"
    }
  }
}

##### Spacing Tokens

Spacing tokens define values for gaps, margins, paddings, and standardized spacing styles to ensure consistent layout structure.

**Example**

{
  spacing: {
    tokens: {
      "space-0": "0",
      "space-1": "0.25rem",
      "space-2": "0.5rem",
      "space-4": "1rem",
      "space-8": "2rem"
    },
    margin: {
      "m-0": "0",
      "m-1": "0.25rem",
      "m-auto": "auto"
    },
    padding: {
      "p-0": "0",
      "p-1": "0.25rem",
      "p-4": "1rem"
    },
    style: {
      card: {
        margin: "1rem",
        padding: "1.5rem"
      }
    }
  }
}

##### Typography Tokens

Typography tokens define text-related properties such as color, weight, size, line height, letter spacing, and typographic styles used across the interface.

**Example**

{
  typography: {
    color: {
      "text-primary": "#007bff",
      "text-secondary": "#6c757d",
      "text-muted": "#6c757d"
    },
    fontWeight: {
      "font-light": 300,
      "font-normal": 400,
      "font-medium": 500,
      "font-semibold": 600,
      "font-bold": 700
    },
    fontSize: {
      "text-xs": "0.75rem",
      "text-sm": "0.875rem",
      "text-base": "1rem",
      "text-lg": "1.125rem",
      "text-xl": "1.25rem"
    },
    lineHeight: {
      "leading-none": 1,
      "leading-tight": 1.25,
      "leading-normal": 1.5,
      "leading-relaxed": 1.75
    },
    letterSpacing: {
      "tracking-tighter": "-0.05em",
      "tracking-tight": "-0.025em",
      "tracking-normal": "0em",
      "tracking-wide": "0.025em"
    },
    style: {
      heading: {
        fontFamily: "Inter, sans-serif",
        fontWeight: "600",
        fontSize: "1.5rem",
        lineHeight: 1.2,
        letterSpacing: "-0.025em"
      }
    }
  }
}

##### Background Tokens

Background tokens define background colors and reusable background styles to ensure visual consistency across components and sections.

**Example**

{
  background: {
    color: {
      "bg-primary": "#007bff",
      "bg-secondary": "#6c757d",
      "bg-light": "#f8f9fa"
    },
    style: {
      "gradient-primary": {
        type: "linear-gradient",
        angle: 135,
        stops: \["#667eea", "#764ba2"\]
      },
      "gradient-radial": {
        type: "radial-gradient",
        position: "center",
        stops: \["#f093fb", "#f5576c"\]
      },
      "hero-image": {
        type: "image",
        url: "/images/hero-bg.jpg",
        size: "cover",
        repeat: "no-repeat",
        align: "center"
      }
    }
  }
}

##### Border Tokens

Border tokens define border colors, radii, and border style configurations for consistent component framing.

**Example**

{
  border: {
    color: {
      "border-primary": "#007bff",
      "border-secondary": "#6c757d",
      "border-light": "#dee2e6"
    },
    radius: {
      "rounded-none": "0",
      "rounded-sm": "0.125rem",
      "rounded": "0.25rem",
      "rounded-md": "0.375rem",
      "rounded-lg": "0.5rem",
      "rounded-full": "9999px"
    },
    style: {
      button: {
        style: "solid",
        width: "2px",
        color: "#007bff",
        radius: "0.375rem"
      },
      card: {
        style: "solid",
        width: "1px",
        color: "#dee2e6",
        radius: "0.5rem"
      }
    }
  }
}

##### Shadow Tokens

Shadow tokens define shadow colors and predefined shadow presets to create depth and elevation in the interface.

**Example**

{
  shadow: {
    color: {
      "shadow-light": "rgba(0, 0, 0, 0.1)",
      "shadow-medium": "rgba(0, 0, 0, 0.15)",
      "shadow-dark": "rgba(0, 0, 0, 0.25)"
    },
    style: {
      sm: {
        x: "0",
        y: "1px",
        blur: "2px",
        spread: "0",
        color: "rgba(0, 0, 0, 0.05)"
      },
      md: {
        x: "0",
        y: "4px",
        blur: "6px",
        spread: "-1px",
        color: "rgba(0, 0, 0, 0.1)"
      },
      lg: {
        x: "0",
        y: "10px",
        blur: "15px",
        spread: "-3px",
        color: "rgba(0, 0, 0, 0.1)"
      }
    }
  }
}

##### Transform Tokens

Transform tokens define reusable transform configurations, such as scaling, rotation, and translation, to maintain consistent motion and layout behavior.

**Example**

{
  transform: {
    style: {
      "hover-lift": {
        translateY: "-2px",
        scaleX: "1.02",
        scaleY: "1.02"
      },
      "rotate-45": {
        rotateZ: "45deg"
      },
      "skew-x": {
        skewX: "10deg"
      }
    }
  }
}

##### Effects Tokens

Effects tokens define reusable visual effect configurations, such as filters and blurs, to enhance the appearance of UI elements consistently.

**Example**

{
  effects: {
    filter: {
      "blur-sm": "blur(4px)",
      "blur": "blur(8px)",
      "blur-md": "blur(12px)",
      "brightness-75": "brightness(0.75)",
      "brightness-90": "brightness(0.9)",
      "contrast-125": "contrast(1.25)"
    }
  }
}

##### Position and Layout Tokens

Position and layout tokens define layering properties and spatial configurations to control element stacking and structural layout across the interface.

**Example**

{
  position: {
    zIndex: {
      "z-0": "0",
      "z-10": "10",
      "z-20": "20",
      "z-30": "30",
      "z-40": "40",
      "z-50": "50"
    },
    position: {
      "static": "static",
      "relative": "relative",
      "absolute": "absolute",
      "fixed": "fixed",
      "sticky": "sticky"
    }
  },
  layout: {
    gap: {
      "gap-0": "0",
      "gap-1": "0.25rem",
      "gap-2": "0.5rem",
      "gap-4": "1rem",
      "gap-8": "2rem"
    }
  }
}

##### Visibility Tokens

Visibility tokens define opacity and visibility levels to manage element transparency and display behavior consistently.

**Example**

{
  visibility: {
    opacity: {
      "opacity-0": "0%",
      "opacity-25": "25%",
      "opacity-50": "50%",
      "opacity-75": "75%",
      "opacity-100": "100%"
    }
  }
}

##### Overflow Tokens

Overflow tokens define scrolling and clipping behaviors to control how content is displayed when it exceeds its container boundaries.

**Example**

{
  overflow: {
    style: {
      "scroll": "scroll",
      "auto": "auto",
      "hidden": "hidden",
      "visible": "visible",
      "clip": "clip"
    }
  }
}

#### registerDesignTokens Optional Configuration Objects

The following parameters of the registerDesignTokens method are optional configuration objects that define how tokens are processed and which values are permitted.

##### allowDefaultDesignTokens

The allowDefaultDesignTokens option determines whether to merge custom design tokens with built-in defaults (true) or use only the custom tokens provided (false).

**Use**

Set true to inherit sensible defaults, or set false for a fully bespoke system.

**Type:** boolean

**Example**

// Include built-in tokens (recommended for most use cases)
const tokens = registerDesignTokens({
  colorTokens: {
    brand: "#ff6b6b",
    accent: "#4ecdc4"
  }
}, {
  allowDefaultDesignTokens: true
});

// Use only custom tokens
const customTokens = registerDesignTokens({
  colorTokens: {
    brand: "#ff6b6b",
    accent: "#4ecdc4"
  }
}, {
  allowDefaultDesignTokens: false
});

##### allowedValuesLevel

The allowedValuesLevel option governs the level of control authors have when selecting or inputting values in Studio.

**Use**

*   dynamic: Most restrictive option. Only allows linking design properties through data sources. Ideal when design values are strictly managed in the CMS.
*   tokens: Moderate flexibility. Allows both predefined design tokens and data binding, but does not allow arbitrary custom values.
*   arbitrary: Most flexible option. Permits the use of tokens, data binding, and free-form custom values entered manually.

**Type:** tokens, dynamic, and arbitrary

**Example**

// Development environment - maximum flexibility
const devTokens = registerDesignTokens({
  colorTokens: {
    brand: "#ff6b6b",
    accent: "#4ecdc4"
  },
  spacing: {
    tokens: {
      "space-custom": "2rem"
    }
  }
}, {
  allowDefaultDesignTokens: true,
  allowedValuesLevel: "arbitrary"
});

// Production environment - strict consistency
const prodTokens = registerDesignTokens({
  colorTokens: {
    brand: "#ff6b6b",
    accent: "#4ecdc4"
  }
}, {
  allowDefaultDesignTokens: false,
  allowedValuesLevel: "dynamic"
});

// Hybrid approach - built-ins with moderate flexibility
const hybridTokens = registerDesignTokens({
  colorTokens: {
    brand: "#ff6b6b"
  }
}, {
  allowDefaultDesignTokens: true,
  allowedValuesLevel: "arbitrary"
});

#### Default Design Tokens

The DEFAULT\_DESIGN\_TOKENS object provides a predefined set of design tokens that establish consistent styling across components. It includes tokens for colors, typography, spacing, layout, borders, shadows, and other visual properties. These tokens act as reusable values that help maintain design consistency and simplify UI customization in Studio.

const DEFAULT\_DESIGN\_TOKENS = {
  colorTokens: {
    "color-dark": "#000000",
    "color-primary": "#6c5ce7",
    "color-white": "#ffffff",
    "color-secondary": "#475161",
  },

  size: {
    width: SIZE\_TOKENS,
    height: SIZE\_TOKENS,
    minWidth: SIZE\_TOKENS,
    minHeight: SIZE\_TOKENS,
    maxWidth: SIZE\_TOKENS,
  },

  layout: {
    gap: {
      "gap-2": "0.125rem",
      "gap-4": "0.25rem",
      "gap-5": "0.3125rem",
      "gap-6": "0.375rem",
      "gap-8": "0.5rem",
      "gap-10": "0.625rem",
      "gap-12": "0.75rem",
      "gap-14": "0.875rem",
      "gap-15": "0.9375rem",
      "gap-16": "1rem",
    },
  },

  typography: {
    fontSize: {
      "font-size-sm": "0.75rem",
      "font-size-md": "0.875rem",
      "font-size-base": "1rem",
      "font-size-lg": "1.25rem",
      "font-size-xl": "1.75rem",
      "font-size-2xl": "2.125rem",
    },
    fontWeight: {
      "font-regular": 400,
      "font-medium": 500,
      "font-semi-bold": 600,
      "font-bold": 700,
      "font-extra-bold": 800,
    },
    lineHeight: {
      "line-height-default": 1.5,
      "line-height-sm": 1.25,
      "line-height-xs": 1,
    },
    color: {
      "color-dark": "#000000",
      "color-primary": "#6c5ce7",
      "color-white": "#ffffff",
      "color-secondary": "#475161",
    },
  },

  border: {
    radius: {
      "border-radius-xs": "2px",
      "border-radius-sm": "4px",
      "border-radius-md": "6px",
      "border-radius-lg": "8px",
      "border-radius-xl": "10px",
      "border-radius-50": "50%",
      "border-radius-full": "9999px",
    },
    color: {
      "color-lighter": "#f5f5f5",
      "color-light": "#a9b6cb",
      "color-base": "#647696",
      "color-dark": "#475161",
      "color-link": "#6c5ce7",
      "color-focus": "#edf1f7",
      "color-warning": "#d62400",
      "color-success": "#007a52",
    },
  },

  spacing: {
    tokens: {
      "space-2": "0.125rem",
      "space-4": "0.25rem",
      "space-5": "0.3125rem",
      "space-6": "0.375rem",
      "space-8": "0.5rem",
      "space-10": "0.625rem",
      "space-12": "0.75rem",
      "space-14": "0.875rem",
      "space-15": "0.9375rem",
      "space-16": "1rem",
      "space-18": "1.125rem",
      "space-20": "1.25rem",
      "space-22": "1.375rem",
      "space-24": "1.5rem",
      "space-25": "1.5625rem",
      "space-26": "1.625rem",
      "space-28": "1.75rem",
      "space-30": "1.875rem",
      "space-32": "2rem",
      "space-34": "2.125rem",
      "space-35": "2.1875rem",
      "space-36": "2.25rem",
      "space-38": "2.375rem",
      "space-40": "2.5rem",
      "space-50": "3.125rem",
      "space-60": "3.75rem",
      "space-80": "5rem",
      "space-100": "6.25rem",
      "space-160": "10rem",
    },
  },

  background: {
    color: {
      "color-dark": "#000000",
      "color-primary": "#6c5ce7",
      "color-white": "#ffffff",
      "color-secondary": "#475161",
    },
  },

  position: {
    zIndex: {
      "z-index-default": "0",
      "z-index-positive": "1",
      "z-index-negative": "-1",
      "z-index-deepdive": "-99999",
    },
  },

  visibility: {
    opacity: {
      "opacity-0": "0%",
      "opacity-10": "10%",
      "opacity-20": "20%",
      "opacity-40": "40%",
      "opacity-50": "50%",
      "opacity-80": "80%",
      "opacity-100": "100%",
    },
  },

  shadow: {
    style: {
      default: { x: "0px", y: "1px", blur: "3px", spread: "0px", color: "rgba(0, 0, 0, 0.08)" },
      heavy: { x: "0px", y: "2px", blur: "3px", spread: "0px", color: "rgba(0, 0, 0, 0.35)" },
      "light-purple-1px": { x: "0px", y: "0px", blur: "2px", spread: "0px", color: "rgba(0, 0, 0, 0.14)" },
      "light-purple-2px": { x: "0px", y: "2px", blur: "2px", spread: "0px", color: "rgba(0, 0, 0, 0.12)" },
      "light-purple-3px": { x: "0px", y: "1px", blur: "3px", spread: "0px", color: "rgba(108, 92, 231, 0.2)" },
      "light-purple-4px": { x: "0px", y: "2px", blur: "4px", spread: "0px", color: "rgba(0, 0, 0, 0.14)" },
      "light-purple-5px": { x: "0px", y: "5px", blur: "5px", spread: "0px", color: "rgba(0, 0, 0, 0.12)" },
      "light-purple-10px": { x: "0px", y: "1px", blur: "10px", spread: "0px", color: "rgba(108, 92, 231, 0.2)" },
      "light-purple-10px-1": { x: "0px", y: "8px", blur: "10px", spread: "1px", color: "rgba(0, 0, 0, 0.14)" },
      "light-purple-14px": { x: "0px", y: "3px", blur: "14px", spread: "3px", color: "rgba(0, 0, 0, 0.12)" },
      "light-purple-15px": { x: "0px", y: "4px", blur: "15px", spread: "0px", color: "rgba(108, 92, 231, 0.2)" },
      "light-purple-24px": { x: "0px", y: "16px", blur: "24px", spread: "2px", color: "rgba(0, 0, 0, 0.14)" },
      "light-purple-30px": { x: "0px", y: "6px", blur: "30px", spread: "5px", color: "rgba(0, 0, 0, 0.12)" },
      "light-purple-10px-3": { x: "0px", y: "8px", blur: "10px", spread: "3px", color: "rgba(108, 92, 231, 0.2)" },
      "light-purple-38px": { x: "0px", y: "24px", blur: "38px", spread: "3px", color: "rgba(0, 0, 0, 0.14)" },
      "light-purple-46px": { x: "0px", y: "9px", blur: "46px", spread: "8px", color: "rgba(0, 0, 0, 0.12)" },
      "light-purple-15px-8": { x: "0px", y: "11px", blur: "15px", spread: "8px", color: "rgba(108, 92, 231, 0.2)" },
      "black-1px": { x: "0px", y: "0px", blur: "2px", spread: "0px", color: "rgba(0, 0, 0, 0.14)" },
      "black-2px": { x: "0px", y: "2px", blur: "2px", spread: "0px", color: "rgba(0, 0, 0, 0.12)" },
      "black-3px": { x: "0px", y: "1px", blur: "3px", spread: "0px", color: "rgba(0, 0, 0, 0.2)" },
      "black-4px": { x: "0px", y: "2px", blur: "4px", spread: "0px", color: "rgba(0, 0, 0, 0.14)" },
      "black-5px": { x: "0px", y: "5px", blur: "5px", spread: "0px", color: "rgba(0, 0, 0, 0.12)" },
      "black-10px": { x: "0px", y: "1px", blur: "10px", spread: "0px", color: "rgba(0, 0, 0, 0.2)" },
      "black-10px-1": { x: "0px", y: "8px", blur: "10px", spread: "1px", color: "rgba(0, 0, 0, 0.14)" },
      "black-14px": { x: "0px", y: "3px", blur: "14px", spread: "3px", color: "rgba(0, 0, 0, 0.12)" },
      "black-15px": { x: "0px", y: "4px", blur: "15px", spread: "0px", color: "rgba(0, 0, 0, 0.2)" },
      "black-16px": { x: "0px", y: "16px", blur: "24px", spread: "2px", color: "rgba(0, 0, 0, 0.14)" },
      "black-30px": { x: "0px", y: "6px", blur: "30px", spread: "5px", color: "rgba(0, 0, 0, 0.12)" },
      "black-10px-8": { x: "0px", y: "8px", blur: "10px", spread: "0px", color: "rgba(0, 0, 0, 0.2)" },
      "black-38px": { x: "0px", y: "24px", blur: "38px", spread: "3px", color: "rgba(0, 0, 0, 0.14)" },
      "black-46px": { x: "0px", y: "9px", blur: "46px", spread: "8px", color: "rgba(0, 0, 0, 0.12)" },
      "black-15px-2": { x: "0px", y: "11px", blur: "15px", spread: "0px", color: "rgba(0, 0, 0, 0.2)" },
    },
  },
};

## registerDesignClasses

The registerDesignClasses method registers design classes with the design registry, making predefined styling combinations available in the **Class** tab of the **Design** section in Studio. These classes can be applied to components, and the method returns an object containing them for use in component props with type safety.

**Parameters**

**Name**

**Type**

**Description**

designClasses

DesignClassesInput\[\]

An array of class definitions. Accepts either strings or objects with { name, displayName }.

**Returns**

**Type:** DesignClassesNames<C>

**Value:** An object that maps each registered class name to its corresponding value.

**Example:**

{
  primary: "primary",
  card: "card"
}

#### Input Variants

##### String Input (Simple):

Provide class names only. The registry automatically returns a key–value map of those names.

**Example**

const classes = registerDesignClasses(\[
  'primary',
  'secondary',
  'success',
  'danger'
\]);

// Returns:
// { 
//   primary: 'primary', 
//   secondary: 'secondary', 
//   success: 'success', 
//   danger: 'danger' 
// }

##### Object Input (With Display Names):

Provide { name, displayName } to show a user-friendly label in Studio while keeping the internal name stable.

**Example**

const classes = registerDesignClasses(\[
  { name: 'primary', displayName: 'Primary Button' },
  { name: 'secondary', displayName: 'Secondary Button' },
  { name: 'outline', displayName: 'Outline Style' }
\]);

// Returns:
// { 
//   primary: 'primary', 
//   secondary: 'secondary', 
//   outline: 'outline' 
// }

#### Complete Example

import { registerDesignClasses } from '@contentstack/studio-react';

// Register design classes for a button component system
const buttonClasses = registerDesignClasses(\[
  // Simple variants
  'primary',
  'secondary',
  'success',
  'danger',
  'warning',
  'info',

  // Named variants with display names
  { name: 'outline-primary', displayName: 'Primary Outline' },
  { name: 'outline-secondary', displayName: 'Secondary Outline' },
  { name: 'ghost-primary', displayName: 'Primary Ghost' },
  { name: 'ghost-secondary', displayName: 'Secondary Ghost' },

  // Size variants
  { name: 'sm', displayName: 'Small' },
  { name: 'md', displayName: 'Medium' },
  { name: 'lg', displayName: 'Large' },

  // Special styles
  { name: 'rounded', displayName: 'Rounded' },
  { name: 'pill', displayName: 'Pill Shape' },
  { name: 'block', displayName: 'Full Width' }
\]);

console.log(buttonClasses);

// Returns:
// {
//   primary: 'primary',
//   secondary: 'secondary',
//   success: 'success',
//   danger: 'danger',
//   warning: 'warning',
//   info: 'info',
//   'outline-primary': 'outline-primary',
//   'outline-secondary': 'outline-secondary',
//   'ghost-primary': 'ghost-primary',
//   'ghost-secondary': 'ghost-secondary',
//   sm: 'sm',
//   md: 'md',
//   lg: 'lg',
//   rounded: 'rounded',
//   pill: 'pill',
//   block: 'block'
// }

**Usage in Components**

Wire registered classes directly into component props for type safety and consistency:

// In your component registration
props: {
  variant: {
    type: "choice",
    displayName: "Button Variant",
    choices: Object.values(buttonClasses), // Use registered class names
    defaultValue: "primary"
  },
  size: {
    type: "choice",
    displayName: "Button Size",
    choices: \["sm", "md", "lg"\],
    defaultValue: "md"
  }
}

## getDesignTokens

The getDesignTokens method retrieves the currently registered design tokens from the design registry.

**Example**

import { getDesignTokens } from '@contentstack/studio-react';
const tokens = getDesignTokens();

**Returns**

DesignTokens**:** All active tokens, normalized and mapped to CSS variables.

**Usage Example**

import { getDesignTokens } from '@contentstack/studio-react';

// Get current design tokens
const currentTokens = getDesignTokens();

console.log(currentTokens.typography.color);
// Returns: { "text-primary": "var(--token-text-primary)", ... }

console.log(currentTokens.spacing.margin);
// Returns: { "m-0": "var(--token-m-0)", "m-1": "var(--token-m-1)", ... }

## extractStyles

The extractStyles method extracts CSS from composition specifications for Server-Side Rendering (SSR). It generates static CSS that can be injected into the <head> of an HTML document during SSR.

**Parameters**

**Name**

**Type**

**Description**

specs

(StudioSpec | null)\[\]

Array of composition specifications to extract styles from. null entries are ignored.

**Returns**

string: Combined CSS including root base styles, composition-specific styles, and utility styles.

**Example**

import { extractStyles } from '@contentstack/studio-react';

const cssStyles = extractStyles(\[compositionSpec\]);

**Usage Example: SSR Applications**

// In your Next.js or similar SSR framework
import { extractStyles } from '@contentstack/studio-react';

export async function generateStaticParams() {
  const { specOptions } = await useCompositionSpec({ ... });
  const cssStyles = extractStyles(\[specOptions\]);
  return {
    props: {
      cssStyles,
      specOptions
    }
  };
}

export default function Page({ cssStyles, specOptions }) {
  return (
    <>
      <style dangerouslySetInnerHTML={{ \_\_html: cssStyles }} />
      <StudioComponent specOptions={specOptions} />
    </>
  );
}

## Breakpoint Registry

The Breakpoint Registry defines responsive breakpoints in Studio and controls how content adapts to different screen sizes. By default, mobile, tablet, and desktop breakpoints are available. You can also register additional custom breakpoints if needed.

## registerBreakpoints

The registerBreakpoints method registers breakpoints for responsive design. Breakpoints can be selected from the **Viewport** icon in the Studio navigation bar.

**Example:**

import { registerBreakpoints } from '@contentstack/studio-react';

registerBreakpoints(\[
  {
    id: "default",
    displayName: "Desktop",
    previewSize: {
      width: 1200,
      height: 800,
    },
  },
  {
    id: "Iphone 15",
    displayName: "Iphone 15",
    query: "(max-width: 428px)",
    previewSize: {
      width: 375,
      height: 812,
    },
  },
\]);

#### Breakpoint Options

Each breakpoint includes configuration details that specify its identifier, display name, activation conditions, and preview dimensions within Studio’s responsive view.

##### id

The id property defines the unique identifier for the breakpoint.

**Type:** string

**Requirements:**

*   The first breakpoint must have id: "default" (this is the base breakpoint).
*   No duplicate IDs allowed.
*   IDs are case-sensitive (e.g., "Mobile" and "mobile" are different).

##### displayName

The displayName property defines the human-readable name shown in the UI.

**Type:** string | undefined

**Behavior:**

*   Optional; if omitted, the id is used as the display name.
*   Recommended to use descriptive names such as "iPhone 15" or "Tablet Portrait".

##### query

The query property defines the CSS media query that activates the breakpoint.

**Type:** string | undefined

**Requirements:**

*   Default breakpoint: Must not include a query; it is automatically set to \*.
*   Non-default breakpoints: Must include a valid media query.
*   Examples: (max-width: 768px), (min-width: 1024px), and (max-width: 1200px).

##### previewSize

The previewSize property defines the preview canvas dimensions used when the breakpoint is selected.

**Type:** object

**Requirements:**

*   width (number): preview width in pixels.
*   height (number): preview height in pixels.

**Note:** The preview size must fall within the range defined by the query.

**Example: Preview size for mobile and tablet**

// Mobile portrait
previewSize: {
  width: 375,
  height: 812
}

// Tablet landscape
previewSize: {
  width: 1024,
  height: 768
}

##### Basic responsive breakpoints

The following code registers default responsive breakpoints for desktop, tablet, and mobile views with defined preview sizes.

registerBreakpoints(\[
  {
    id: "default",
    displayName: "Desktop",
    previewSize: {
      width: 1200,
      height: 800,
    },
  },
  {
    id: "tablet",
    displayName: "Tablet",
    query: "(max-width: 1024px)",
    previewSize: {
      width: 768,
      height: 1024,
    },
  },
  {
    id: "mobile",
    displayName: "Mobile",
    query: "(max-width: 768px)",
    previewSize: {
      width: 375,
      height: 812,
    },
  },
\]);

##### Device-specific breakpoints

The following code registers custom responsive breakpoints for specific devices.

registerBreakpoints(\[
  {
    id: "default",
    displayName: "Desktop Large",
    previewSize: {
      width: 1440,
      height: 900,
    },
  },
  {
    id: "iphone-15",
    displayName: "iPhone 15",
    query: "(max-width: 428px)",
    previewSize: {
      width: 375,
      height: 812,
    },
  },
  {
    id: "ipad-pro",
    displayName: "iPad Pro",
    query: "(max-width: 1024px) and (min-width: 769px)",
    previewSize: {
      width: 1024,
      height: 768,
    },
  },
\]);

##### Minimal configuration (auto-filled displayName)

The following code registers responsive breakpoints with minimal configuration, automatically generating display names for each device.

registerBreakpoints(\[
  {
    id: "default",
    previewSize: {
      width: 1200,
      height: 800,
    },
  },
  {
    id: "mobile",
    query: "(max-width: 768px)",
    previewSize: {
      width: 375,
      height: 812,
    },
  },
\]);

#### Default Breakpoints

By default, the following breakpoints are included:

*   **Desktop** (id: "default")
*   **Tablet** (id: "tablet")
*   **Mobile** (id: "mobile")

**Example**

const DEFAULT\_BREAKPOINTS = \[
  {
    id: "default",
    displayName: "Desktop",
    previewSize: {
      width: 1200,
      height: 800,
    },
  },
  {
    id: "tablet",
    displayName: "Tablet",
    query: "(max-width: 1023px)",
    previewSize: {
      width: 800,
      height: 600,
    },
  },
  {
    id: "mobile",
    displayName: "Mobile",
    query: "(max-width: 767px)",
    previewSize: {
      width: 400,
      height: 500,
    },
  },
\];

## Types & Interfaces

The Types & Interfaces defines the core type structures in the Studio SDK. These structures ensure type safety, consistency, and interoperability between components, design tokens, and composition specifications.

## Spec-Related Types

The Spec-Related Types section defines type structures for compositions, design tokens, and component attributes in the Studio SDK. These definitions maintain data accuracy, UI consistency, and reliable interaction across Studio components.

#### StudioSpec

The StudioSpec type represents the complete composition specification, including UI structure, data, and metadata required for rendering compositions.

#### DesignTokensInput

The DesignTokensInput type defines the input object used when registering design tokens, specifying the structure and categories that form the basis of the design system.

#### StudioAttributes

The StudioAttributes type is required when registering a component with wrap: false. This attribute is required for the StudioComponent to work. Extend your component props with this attribute to ensure full compatibility.

**Example**

import { StudioAttributes } from "@contentstack/studio-react";

interface MyComponentProps extends StudioAttributes {
  title: string;
}

const MyComponent = ({ studioAttributes, title }: MyComponentProps) => {
  return (
    <div {...studioAttributes}>
      <h2>{title}</h2>
    </div>
  );
};

#### StudioComponentSpecOptions

The StudioComponentSpecOptions type is used to render a composition specification. It is passed to the StudioComponent and can be obtained either from the useCompositionSpec hook or from the fetchCompositionSpec method of the StudioSdk instance.

#### CslpTag

The CslpTag type is used to annotate CSLP attributes, which identify data in Live Preview and Visual Builder.

## Usage Examples

#### Basic Usage

The following example demonstrates initializing the SDK, fetching a composition, and rendering it with the StudioComponent.

import {
  registerDesignTokens,
  registerDesignClasses,
  registerBreakpoints
} from '@contentstack/studio-react';

// Register design tokens
const tokens = registerDesignTokens({
  colors: {
    primary: '#007bff',
    secondary: '#6c757d'
  },
  spacing: {
    sm: '0.5rem',
    md: '1rem',
    lg: '1.5rem'
  }
});

// Register design classes
const classes = registerDesignClasses(\[
  { name: 'primary', displayName: 'Primary' },
  { name: 'secondary', displayName: 'Secondary' }
\]);

// Register breakpoints
registerBreakpoints(\[
  { name: 'mobile', maxWidth: 768 },
  { name: 'tablet', minWidth: 769, maxWidth: 1024 },
  { name: 'desktop', minWidth: 1025 }
\]);