Adding New Components and Customizing Existing Ones

Last updated: June 16, 2026

Problem Statement

Every project eventually needs custom components that integrate cleanly with the Component Starter Kit (CSK) without breaking its update path. You may also need to override logic in existing core components while still reusing them.

Solution

1. Understand the component resolver structure

Every canvas component must be registered and passed to the main resolveComponent function. The CSK separates core and custom components into two mappers, so core updates stay safe and custom components are easy to add or remove. This is already set up in src/components/index.ts:

import { cskComponentsMapping } from '@/components/canvas';
import { customComponentsMapping } from '@/components/custom-canvas';

import createComponentResolver, { ComponentMapping } from '@/utils/createComponentResolver';

const componentsMapping: ComponentMapping = {
  ...cskComponentsMapping,
  ...customComponentsMapping,
};

const componentResolver = createComponentResolver(componentsMapping);

export default componentResolver;

2. Add a new custom component

  1. Define the component on the canvas side first: parameters, slots, and any additional settings.

  2. Create the component in code to read and render that canvas data. See the included example at src/components/custom-canvas/CustomComponent.tsx:

import { FC } from 'react';
import { ComponentProps, UniformSlot, UniformText } from '@uniformdev/canvas-next-rsc/component';

// Parameters used on the canvas side.
export type CustomComponentParameters = {
  displayName?: string;
};
// Slot names used on the canvas side.
enum CustomComponentSlots {
  CustomComponentContent = 'customComponentContent',
}

type CustomComponentProps = ComponentProps<CustomComponentParameters, CustomComponentSlots>;

const CustomComponent: FC<CustomComponentProps> = ({ component, context, slots }) => (
  <div>
    <UniformText
      placeholder="Text goes here"
      parameterId="displayName"
      as="h1"
      component={component}
      context={context}
    />
    <UniformSlot data={component} context={context} slot={slots.customComponentContent} />
  </div>
);

export default CustomComponent;
  1. Register it in src/components/custom-canvas/index.ts:

import { ComponentMapping } from '@/utils/createComponentResolver';
import Container from './Container';
import CustomComponent from './CustomComponent';

export const customComponentsMapping: ComponentMapping = {
  // Your own component.
  customComponent: CustomComponent,
  // An overridden CSK Container component.
  container: Container,
};

3. Customize an existing core component

  1. Import the core component you want to override.

  2. Wrap it, modifying or adding properties and logic as needed. Example at src/components/custom-canvas/Container.tsx:

import { FC } from 'react';
import CSKContainer, { ContainerProps as CSKContainerProps } from '@/components/canvas/Container';

const Container: FC<CSKContainerProps> = props => <CSKContainer {...props} />;

export default Container;
  1. Register the override in src/components/custom-canvas/index.ts using the same name as the existing component (see container: Container in the mapping above) so it replaces the core version.

Troubleshooting

Verify it works: add your custom component to a composition on the canvas — it should render with its parameters and slot content; the overridden Container should render wherever Container is used.

Custom component doesn't render: confirm it's registered in customComponentsMapping and that the mapping is spread into the resolver in src/components/index.ts.

Override has no effect: the key in customComponentsMapping must exactly match the existing component's name (e.g. container), since custom mappings are spread after the core ones.