Registration
Register components in thecomponents array of your config. Each entry needs a name, an importPath for Studio to resolve the component, and optionally a description and propHints:
mdcms.config.ts
Registration options
| Option | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Component name. Must match the exported React component name. |
importPath | string | Yes | Module path for Studio to resolve the component at runtime. |
description | string | No | Shown in the component catalog to help authors pick the right component. |
load | () => Promise<unknown> | No | Dynamic import function for Studio to load the component at runtime. |
propHints | Record<string, PropHint> | No | Override auto-detected prop types with specific widgets. |
propsEditor | string | No | Module path to a custom props editor component, for complex editing UIs. |
loadPropsEditor | () => Promise<unknown> | No | Dynamic import for the custom props editor. |
Prop extraction
MDCMS uses TypeScript’s compiler API to extract prop types from your component source files. Each prop is mapped to a form control in Studio based on its type:| TypeScript type | Extracted type | Studio control |
|---|---|---|
string | string | Text input |
number | number | Number input |
boolean | boolean | Toggle switch |
Date | date | Date picker |
"a" | "b" | "c" (string literal union) | enum | Dropdown select |
string[] | array (items: string) | Tag input |
number[] | array (items: number) | Repeatable number inputs |
ReactNode / children | rich-text | Nested rich-text editor |
JSON-serializable object (with json hint) | json | JSON editor |
Props with function types, ref types, or other non-serializable types are
automatically excluded from the form. Only serializable props appear in the
Studio editor.
Example component
components/mdx/Callout.tsx
typeasenumwith values["info", "warning", "error"](dropdown)titleasstring(text input)childrenasrich-text(nested content editor)
Prop hints
Prop hints override the auto-detected form control for a given prop. Use them when the default control doesn’t match the intended input experience.Available hints
format: url
format: url
Renders a text input with URL validation. Only valid for
string props.widget: color-picker
widget: color-picker
Renders a color picker input. Only valid for
string props.widget: textarea
widget: textarea
Renders a multi-line textarea instead of a single-line text input. Only valid for
string props.widget: slider
widget: slider
Renders a range slider. Only valid for
number props. Requires min and max; step is optional.widget: image
widget: image
Renders an image picker/uploader. Only valid for
string props (stores the image URL).widget: select
widget: select
Renders a dropdown with explicit options. Valid for
string, number, boolean, or enum props. Options can be simple values or { label, value } objects.widget: hidden
widget: hidden
widget: json
widget: json
Renders a JSON editor for complex structured data. Only valid for props whose TypeScript type is JSON-serializable.
Inserting components in Studio
Content authors can insert registered components in two ways:Slash command
Type
/ in the editor to open the command palette. The component catalog
shows all registered components with their names and descriptions.Output format
Inserted components are written as standard MDX syntax in the document body:children (rich-text) props render as wrapper tags with nested content.
Wrapper components
If your component accepts achildren prop typed as ReactNode, it becomes a wrapper component. Studio renders a content hole inside the component block where authors can write rich text, insert other components, or add any editor content.
components/mdx/Callout.tsx
children prop are void components — they render as self-closing tags and don’t accept nested content.