Working with Widgets

Widgets in BCMS are reusable content blocks used inside the content area of entries. They let you group and reuse predefined sets of properties like: buttons, testimonials, video embeds, sliders, and more.

You create and manage widgets from the Widgets section in the BCMS dashboard. Once created, you can insert widgets into any entry content field.

Creating and editing a widget

To create a widget:

  1. Go to Widgets in the sidebar.

  2. Click Create new widget.

  3. Enter a label and an optional description.

To edit a widget:

  • Click the widget you want to update.

  • Modify the label, description, or properties.

main.jpg

You can also update widget definitions programmatically using the BCMS Client SDK:

const allWidgets = await bcms.widget.getAll();

const singleWidget = await bcms.widget.getById('widget_id');

Adding properties to a widget

Once you've created a widget, drag and configure properties just like you would with templates. You can define types such as string, number, media, group, and more. These fields will later be accessible when editing entries that use this widget.

Deleting a widget

To delete a widget:

  1. Open the widget you want to remove.

  2. Click Edit widget.

  3. Click Delete widget.

⚠️ Deleting a widget removes it from all entries where it's used. Be sure to check where it’s used before deleting to avoid breaking live content.

Widgets can’t be deleted via the SDK. Always delete them manually from the dashboard.


Where is a widget used?

To find out where a widget is used, you can call:

const usage = await bcms.widget.whereIsItUsed('widget_id');

This returns all entry/template pointers where the widget is currently used.


Type-safe widget usage

✅ BCMS automatically generates TypeScript types for all widgets, templates, and groups. You can import these from @bcms-types/ts to get full type safety when rendering widgets.

For example:

import type { TestimonialsWidget } from '@bcms-types/ts';

const Testimonials = ({ data }: { data: TestimonialsWidget }) => {
  return (
    <section>
      {data.testimonials.map((t) => (
        <blockquote key={t.quote}>
          <p>{t.quote}</p>
          <footer>{t.name}</footer>
        </blockquote>
      ))}
    </section>
  );
};

If you're using a custom widget like Testimonials, BCMS will generate a corresponding TestimonialsWidget type you can import and use in your component.


Rendering widgets on the frontend

Installation (React)

npm install @thebcms/components-react

Usage

import { BCMSContentManager } from '@thebcms/components-react';
import { bcms } from './client';
import Testimonials from '@/components/widgets/testimonials';

export default async function Page() {
  const page = await bcms.entry.getById('about-us', 'page');
  return (
    <BCMSContentManager
      items={page.content.en.nodes}
      clientConfig={bcms.getConfig()}
      widgetComponents={{
        testimonials: Testimonials,
      }}
    />
  );
}

What it does

The <BCMSContentManager /> component automatically detects each content node’s type and renders:

  • Primitive content (paragraphs, headings, lists)

  • Media files (images)

  • Widgets (via the widgetComponents prop)

If a widget is not handled (i.e., not registered in widgetComponents), it renders a hidden warning in the DOM:

<div
  style="display: none;"
  data-bcms-widget-error="Widget testimonials is not handled"
>
  Widget testimonials is not handled
</div>

⚠️ Widget keys in widgetComponents must match the widget name used in BCMS (usually lowercase).


Custom rendering (optional)

If, in rear cases, you need complete control, use the nodeParser prop to override how each content node is rendered manually:

<BCMSContentManager
  items={page.content.en.nodes}
  clientConfig={bcms.getConfig()}
  nodeParser={(node) => {
    if (node.type === 'paragraph') {
      return <p className="custom-paragraph">{node.value}</p>;
    }
    return '';
  }}
/>

Conclusion

Widgets offer powerful flexibility and reusability across your content. Define them once, use them anywhere, and render them confidently with automatic typing and structured output.

Pair them with the <BCMSContentManager /> to build dynamic layouts, custom pages, and rich frontend experiences without writing parsing logic manually.