Skip to content

k11k-labs/better-blocks-react-renderer

Repository files navigation

Better Blocks React Renderer

React renderer for Strapi v5 Blocks content — supports all standard blocks plus Better Blocks features: color, highlight, text alignment, nested lists, to-do lists, tables, media embeds, image captions, and more.

npm version npm downloads license

Strapi editor (left) and rendered output (right)


Table of Contents

  1. Why?
  2. Compatibility
  3. Installation
  4. Usage
  5. Supported Blocks
  6. Supported Modifiers
  7. Custom Renderers
  8. TypeScript
  9. Contributing
  10. License

Why?

The official @strapi/blocks-react-renderer doesn't support the features that the Better Blocks plugin adds to the Strapi editor — color marks, text alignment, to-do lists, tables, media embeds, and more.

This package is a drop-in replacement that renders all Better Blocks features out of the box — no configuration needed.

Compatibility

Strapi Version Renderer Version React Version
v5.x v0.x ≥ 17

Installation

# Using yarn
yarn add @k11k/better-blocks-react-renderer

# Using npm
npm install @k11k/better-blocks-react-renderer

Peer dependencies: react >= 17

Usage

import { BlocksRenderer } from '@k11k/better-blocks-react-renderer';

// Basic — renders all blocks including color/highlight
<BlocksRenderer content={blocks} />;

That's it. All Better Blocks features — colors, tables, to-do lists, media embeds, alignment, and more — work automatically.

Supported Blocks

Block Default element Source
paragraph <p> Strapi core
heading (1–6) <h1><h6> Strapi core
list (ordered/unordered/todo) <ol> / <ul> Strapi core + Better Blocks
list-item <li> Strapi core
link <a> Strapi core
quote <blockquote> Strapi core
code <pre><code> Strapi core
image <figure><img> Strapi core
horizontal-line <hr> Better Blocks
table <table> Better Blocks
media-embed <iframe> (16:9) Better Blocks

Block properties

Property Applies to Description
textAlign paragraph, heading, quote Text alignment (left, center, right, justify)
lineHeight paragraph, heading, quote CSS line-height value (e.g. 1.5, 2.0)
indent paragraph, heading, quote Block indentation level (marginLeft: N * 2rem)
indentLevel list Cycling list-style-type per nesting depth
format list ordered, unordered, or todo
checked list-item (in todo lists) Checkbox state (true/false)
target link _blank for new-tab links
rel link noopener noreferrer for new-tab links
caption image Text displayed below the image
imageAlign image Image alignment (left, center, right)
url media-embed Embed URL (YouTube/Vimeo iframe src)
originalUrl media-embed Original user-provided URL

Supported Modifiers

Modifier Default element Source
bold <strong> Strapi core
italic <em> Strapi core
underline <span> Strapi core
strikethrough <del> Strapi core
code <code> Strapi core
uppercase <span style={{textTransform}}> Better Blocks
superscript <sup> Better Blocks
subscript <sub> Better Blocks
color <span style={{color}}> Better Blocks
backgroundColor <span style={{backgroundColor}}> Better Blocks
fontFamily <span style={{fontFamily}}> Better Blocks
fontSize <span style={{fontSize}}> Better Blocks

Custom Renderers

Custom block renderers

Override any block type with your own component:

<BlocksRenderer
  content={blocks}
  blocks={{
    paragraph: ({ children, style }) => (
      <p className="my-paragraph" style={style}>
        {children}
      </p>
    ),
    heading: ({ children, level, style }) => {
      const Tag = `h${level}`;
      return <Tag style={style}>{children}</Tag>;
    },
    link: ({ children, url, target, rel }) => (
      <a href={url} target={target} rel={rel}>
        {children}
      </a>
    ),
    image: ({ image, caption, imageAlign }) => (
      <figure style={{ textAlign: imageAlign }}>
        <img src={image.url} alt={image.alternativeText || ''} loading="lazy" />
        {caption && <figcaption>{caption}</figcaption>}
      </figure>
    ),
    'list-item': ({ children, checked }) =>
      checked !== undefined ? (
        <li style={{ listStyle: 'none' }}>
          <input type="checkbox" checked={checked} readOnly /> {children}
        </li>
      ) : (
        <li>{children}</li>
      ),
    'horizontal-line': () => <hr className="my-divider" />,
    table: ({ children }) => <table className="my-table">{children}</table>,
    'table-header-cell': ({ children }) => <th className="my-th">{children}</th>,
    'table-cell': ({ children }) => <td className="my-td">{children}</td>,
    'media-embed': ({ url }) => (
      <div className="video-wrapper">
        <iframe src={url} allowFullScreen title="Embedded media" />
      </div>
    ),
  }}
/>

Custom modifier renderers

Override any text modifier with your own component:

<BlocksRenderer
  content={blocks}
  modifiers={{
    bold: ({ children }) => <strong className="font-bold">{children}</strong>,
    color: ({ children, color }) => <span style={{ color }}>{children}</span>,
    backgroundColor: ({ children, backgroundColor }) => (
      <mark style={{ backgroundColor }}>{children}</mark>
    ),
  }}
/>

TypeScript

All types are exported:

import type {
  BlocksContent,
  BlocksRendererProps,
  BlockNode,
  TextNode,
  LinkNode,
  ListNode,
  ListItemNode,
  ParagraphNode,
  HeadingNode,
  QuoteNode,
  CodeNode,
  ImageNode,
  HorizontalLineNode,
  TableNode,
  TableRowNode,
  TableCellNode,
  TableHeaderCellNode,
  MediaEmbedNode,
  TextAlign,
  CustomBlocksConfig,
  CustomModifiersConfig,
} from '@k11k/better-blocks-react-renderer';

Contributing

Contributions are welcome! The easiest way to get started is with Docker:

# Clone the repository
git clone https://github.com/k11k-labs/better-blocks-react-renderer.git
cd better-blocks-react-renderer

# Start the playground with Docker
cd playground
docker compose up

This will start a Strapi v5 instance with the Better Blocks plugin and a React app that renders the content — all pre-configured with a showcase article.

Development workflow

  1. Make changes to the renderer source in src/
  2. Rebuild: yarn build (from repo root)
  3. The React app picks up the new build automatically

Without Docker

# Build the renderer
yarn install && yarn build

# Start Strapi
cd playground/strapi && cp .env.example .env && npm install && npm run dev

# Start the React app (in another terminal)
cd playground/react-app && npm install && npm run dev

Running tests

yarn test        # Run tests
yarn test:ts     # Type check
yarn lint        # Check formatting

Community & Support

Related

License

MIT License © k11k-labs