Skip to content

Creating New Components

Adding a new component requires two things: a Content Model in the CMS (the schema) and a React component in your storefront (the renderer). They’re linked by the model’s api_id.

Step-by-step example

This walkthrough adds a TestimonialCard component.

  1. Create the content model in Alokai CMS

    Go to Content Models → New Content Model:

    SettingValue
    NameTestimonial Card
    API IDTestimonialCard
    TypeComponent

    Add these fields:

    NameType
    quoterichtext
    authortext
    roletext
    avatarimage

    Save the model.

  2. Create the React component

    In your storefront, create components/cms/page/testimonial-card.tsx:

    interface TestimonialCardProps {
    quote: string;
    author: string;
    role?: string;
    avatar?: { url: string; alt: string };
    className?: string;
    }
    export default function TestimonialCard({ quote, author, role, avatar, className }: TestimonialCardProps) {
    return (
    <figure className={className}>
    <blockquote dangerouslySetInnerHTML={{ __html: quote }} />
    <figcaption>
    {avatar && <img src={avatar.url} alt={avatar.alt} />}
    <strong>{author}</strong>
    {role && <span>{role}</span>}
    </figcaption>
    </figure>
    );
    }
  3. Register it in render-cms-content.tsx

    Open components/cms/page/render-cms-content.tsx and add your component to the map:

    import TestimonialCard from '@/components/cms/page/testimonial-card';
    const components: Record<string, ComponentType<any>> = {
    // ... existing components
    TestimonialCard,
    };

    The key (TestimonialCard) must exactly match the api_id set in step 1.

  4. Use it in the CMS

    Open any page in Alokai CMS, click + Add in a zone, and select Testimonial Card from the component picker. Fill in the fields and publish.

Passing nested components

If your component contains other components (e.g. a CardGrid that holds multiple Card items), use a components field type in the content model and accept a ReactNode prop in the React component — RenderCmsContent will recursively render children automatically.

// In render-cms-content.tsx, nested `components` fields are resolved
// to rendered React elements before being passed as props.
export default function CardGrid({ components, columns = 3, className }: CardGridProps) {
return (
<div className={`grid grid-cols-${columns} gap-4 ${className}`}>
{components}
</div>
);
}

Using the CLI

Content models and content entries can also be created and seeded programmatically. See the CLI reference for details.

Tips

  • PascalCaseapi_id must be PascalCase and match the key in the component map exactly.
  • Optional fields — make all non-required props optional in TypeScript (prop?: Type) so the component doesn’t break when fields are left empty by editors.
  • Images — image fields are passed as { url: string; alt: string; width?: number; height?: number }.
  • Richtext — richtext fields contain an HTML string. Use dangerouslySetInnerHTML or a sanitising renderer.