By Shyam Verma

Building a 26-Block CMS: How I Made Content Editors Love Headless

Building a 26-Block CMS: How I Made Content Editors Love Headless

The biggest problem with headless CMS: no visual page builder. Here's how I built a 26-block content system that empowers non-technical editors while maintaining code quality and design consistency.

Published on World Accessibility Day 2025 - Accessibility isn't just a feature, it's built into the foundation of this system. Every one of the 26 blocks is WCAG 2.1 compliant by default, ensuring inclusive experiences for all users.

The Headless CMS Problem

When I told the ReelAbilities Film Festival team we were migrating from WordPress to a headless CMS, I got this response:

"So every time we want to change the homepage or add a new section, we'll need to call you?"

This is the #1 blocker to headless CMS adoption.

WordPress Has:

  • Gutenberg block editor (drag-and-drop)
  • Elementor page builder (visual WYSIWYG)
  • 60,000+ plugins for everything
  • Non-technical users productive in 5 minutes
  • Visual preview while editing

Headless CMS Has:

  • Markdown or raw JSON fields
  • No visual page builder
  • Developer dependency for layouts
  • Code changes for new page sections
  • "Call the developer" syndrome

The client's fear was valid. Without a solution, we'd create a developer bottleneck worse than WordPress.

The Challenge

Build a system where:

  • ✅ Content editors can build complex pages independently
  • ✅ Design system constraints are enforced (can't break layouts)
  • ✅ Type safety prevents runtime errors
  • ✅ Performance stays optimal (server-side rendering)
  • ✅ Reusability across 15+ city festival sites
  • ✅ Accessibility built-in (WCAG 2.1 compliant)
  • ✅ No visual builder needed (CMS form-based)

The Solution: A LEGO-Like Block System

I built a block-based content system that rivals WordPress Gutenberg—without the visual builder complexity.

Think of it like LEGO blocks: each piece has a specific shape and purpose, they all snap together perfectly, and you can build anything by combining them in different ways.

System Overview:

  • 26 content blocks (like 26 different LEGO piece types)
  • 20 static blocks (content editors fill in text/images)
  • 6 dynamic blocks (automatically pull data from the database)
  • Type-safe validation (blocks won't "snap together" incorrectly)
  • Auto-generated documentation (instructions for each block type)
  • Built with Next.js 15 and Directus CMS

Result: Content editors building pages faster than WordPress, with zero broken layouts.


Part 1: The Two Types of Blocks

Static Blocks (20 blocks) - "Fill in the Blanks"

These are like form templates. Content editors fill in fields like title, description, and image, and the block displays them in a predefined layout.

Examples:

TwoColumnImageTextBlock - Image on one side, text on the other (like a magazine layout)

TwoColumnImageTextBlock example showing an image on the left side with text content on the right, demonstrating the flexible two-column layout

MultiColumnItemsBlock - Grid of 2-4 items (like a service showcase)

MultiColumnItemsBlock displaying a responsive grid of items with icons, titles, and descriptions in a clean multi-column layout

InfoListBlock - Expandable FAQ-style list

InfoListBlock showing an expandable accordion-style list with a main header and collapsible content sections

NumberedTextBoxBlock - Step-by-step guides with numbers

NumberedTextBoxBlock displaying numbered steps in an organized sequence, perfect for tutorials and process guides

How It Works:

  1. Editor chooses "TwoColumnImageTextBlock" from dropdown
  2. Fills in: title, description, upload image, add button
  3. Configures: Image left or right? Highlight mode on/off?
  4. Publish

The Magic: Editors can't break the design. Fields are validated—if you forget the image, you get a helpful error message instead of a broken page.

Dynamic Blocks (6 blocks) - "Auto-Populate from Database"

These blocks automatically fetch and display data from collections (like events, partners, films).

Examples:

CityScheduleBlock - Shows next 3 upcoming events (auto-updates daily)

CityScheduleBlock automatically displaying upcoming events with dates, times, and event details that update in real-time

CityFeaturedGuestBlock - Highlights featured festival guests

CityFeaturedGuestBlock showcasing featured guests with photos, bios, and credentials in an elegant layout

How It Works:

  1. Editor chooses "CityScheduleBlock"
  2. Sets configuration: "Show 3 events"
  3. Block automatically fetches upcoming events from the database
  4. Publish

The Magic: Content stays fresh without manual updates. When a new event is added to the database, it automatically appears on the homepage.


Part 2: How the System Works (Non-Technical Explanation)

The Registry: A Phone Book for Blocks

Imagine a phone book where you look up a name (block type) and get the address (component to render).

When a page loads:

  1. System reads: "This page has TwoColumnImageTextBlock at position 1"
  2. Looks up in registry: "TwoColumnImageTextBlock = this React component"
  3. Renders that component with the editor's content
  4. Repeat for all blocks on page

Why This Matters: Adding a new block type is as simple as adding a new entry to the phone book. No complex routing, no database migrations.

Validation: The "Smart Snap" System

Remember LEGO blocks that only fit together in certain ways? Our validation does that for content.

Example Validations:

  • TwoColumnImageTextBlock needs exactly 1 item (not 0, not 2)
  • That item must have: title, description, and image
  • MultiColumnItemsBlock needs 2-4 items, or even numbers above 4
  • InfoListBlock's first item must have a title (the main header)

When Validation Fails:
Instead of a broken page, editors see:

Block Validation Error in TwoColumnImageTextBlock:
- Items count must be exactly 1. Found: 0

Clear message, easy fix, no developer needed.

Configuration: Fine-Tuning Without Code

Each block can be customized through simple key-value pairs (like settings in your phone). Same block, infinite variations—no code changes needed.


Part 3: The Content Editor Experience

Building a Homepage in 15 Minutes

Let me show you how a content editor builds a complex page:

Directus CMS page editor showing block sections in the sidebar with live website preview on the right

Step 1: Choose Your Blocks
In the CMS, add block sections like stacking pancakes:

  1. HeroCarouselBlock (auto-rotating images)
  2. TwoColumnImageTextBlock (welcome message)
  3. MultiColumnItemsBlock (4 services in a grid)
  4. CityScheduleBlock (next 3 events, auto-updated)
  5. FeaturedPartnerBlock (partner logos, auto-fetched)
  6. PostRowButtonBlock (big "Register Now" button)

Step 2: Fill in Content
For static blocks, fill in forms:

  • Title: "Welcome to ReelAbilities 2025"
  • Description: "Celebrating inclusion through film..."
  • Upload image
  • Add button: "Learn More" → /about

Block configuration form showing settings for ContentSliderBlock with multiple items and configuration options

For dynamic blocks, just configure:

  • Limit: 3 (show 3 events)
  • Featured: true (only featured partners)

Individual block item editor showing content fields including title, subtitle, description, and image upload

Step 3: Configure Layout

  • Image left or right?
  • Show accent decorations?
  • Background color black or white?
  • Full width or contained?

Step 4: Publish

Time: 15-20 minutes
Developer help needed: Zero
Result: Professional page, impossible to break design

Part 4: Real Feedback from Content Editors

"This is actually easier than Gutenberg once you learn it. I don't have to worry about breaking the design."

— Festival Content Manager

Real-World Impact:

  • 30+ pages built by content team independently
  • Training time: 2 hours (one session)
  • Update time reduced from hours to 15 minutes
  • Developer bottleneck eliminated
  • Time to market: Same-day vs 1-2 weeks previously

Part 5: The Complete Block Catalog

Layout Blocks (for page structure)

  1. TwoColumnImageTextBlock - Image + text side-by-side
  2. TwoColumnThreeItemsBlock - Special 3-item layout
  3. MultiColumnItemsBlock - Grid of 2-4 items (or even numbers)
  4. NumberedTextBoxBlock - Numbered steps (1, 2, 3...)
  5. InfoListBlock - Main item + expandable list

Navigation Blocks (for menus and links)

  1. AccentedNavigationBlock - Stylized section links
  2. ListNavigationBlock - Simple bullet list of links
  3. PostRowButtonBlock - Big CTA button rows

Media Blocks (for visuals)

  1. PostRowImageBlock - Image galleries
  2. PostRowYoutubeBlock - YouTube embeds
  3. PostRowEmbedBlock - Third-party content (maps, forms)
  4. ContentSliderBlock - Full-width image carousels
  5. HeroCarouselBlock - Auto-rotating hero sections

Content Blocks (for text)

  1. PostRowHeaderBlock - Large text headers
  2. PostRowHTMLBlock - Rich text content
  3. PostRowItemBlock - Generic content cards
  4. AccentedTextListBlock - Styled bullet lists
  5. TicketPriceBlock - Pricing information

City-Specific Blocks (for festivals)

  1. CityHomepageHeaderBlock - City landing page hero
  2. CityEventsSliderBlock - Event carousels

Dynamic Data Blocks (auto-updating)

  1. CityScheduleBlock - Upcoming events (auto-updates)
  2. CityFeaturedGuestBlock - Featured speakers
  3. CityFeaturedProgramBlock - Featured programs
  4. FeaturedPartnerBlock - Partner/sponsor logos
  5. ReelEducationGradeBlock - Education grade listings
  6. StreamListBlock - Film catalog (6 display modes)

26 Blocks Total - Like having 26 different LEGO piece types to build any page you need.


Part 6: Documentation System

Each of the 26 blocks has its own guide with:

  • Block overview and use cases
  • Required and optional fields
  • Configuration options
  • Real examples
  • Accessibility notes

Auto-generated documentation site with searchable guides and organized navigation for all 26 blocks

All guides are compiled into a searchable documentation site at /docs with full-text search and category browsing.


Part 7: Comparison to WordPress Gutenberg

What WordPress Does Better:

  • ✅ Visual drag-and-drop
  • ✅ Real-time preview
  • ✅ Familiar interface (millions of users)
  • ✅ Zero training needed

What Our System Does Better:

  • ✅ Can't break the design (validation prevents it)
  • ✅ Faster performance (server-rendered, not JavaScript-heavy)
  • ✅ Type safety (errors caught before publish)
  • ✅ Multi-site reusability (15 festivals, one codebase)
  • ✅ Auto-updating content (dynamic blocks)

The Trade-Off: WordPress is easier to start, our system is more powerful once learned (2-hour learning curve).


Part 8: Lessons Learned

What Worked Exceptionally Well

1. Standardization from Day One

  • All 26 blocks use the same props interface
  • Consistent validation patterns
  • Same configuration system
  • Impact: Easy to add new blocks, patterns are clear

2. Configuration Over Code

  • Block behavior controlled by simple key-value pairs
  • No code changes for layout variations
  • Content editors have power
  • Impact: Developer requests dropped to zero

3. Comprehensive Validation

  • Helpful error messages (not cryptic)
  • Errors caught in development (not production)
  • Prevents broken layouts
  • Impact: Production bugs near zero

4. Documentation-First Approach

  • Every block documented before release
  • Real examples in every guide
  • Searchable documentation site
  • Impact: Training time reduced from days to 2 hours

5. Progressive Complexity

  • Started with 5 simple blocks
  • Perfected the pattern
  • Scaled to 26 blocks
  • Impact: Each new block easier than the last

What I'd Do Differently

1. Build Preview Mode on Day One

  • Content editors want to see before publishing
  • Would have reduced "does this look right?" questions
  • Learning: Preview is not optional, it's essential

2. Visual Block Browser

  • Catalog with screenshots (not just names)
  • "Choose by appearance" would be faster
  • Learning: Names like "MultiColumnItemsBlock" aren't intuitive

Common Pitfalls We Avoided

Pitfall 1: Over-Engineering

  • Could have spent months building a visual builder
  • CMS forms + good docs work great
  • Lesson: Don't build what you don't need

Pitfall 2: Inconsistent Patterns

  • Early blocks had different validation styles
  • Standardized quickly, avoided refactoring pain
  • Lesson: Establish patterns early, enforce them

Pitfall 3: Poor Error Messages

  • First attempt had cryptic errors like "Invalid item"
  • Invested in helpful messages: "Item must have field: image"
  • Lesson: Error messages are part of UX

Pitfall 4: Skipping Documentation

  • Blocks without docs = constant questions
  • Documentation significantly reduced support requests
  • Lesson: Documentation is not optional

Part 9: Key Takeaways

The Core Pattern:

  • Standardize all blocks (same props interface)
  • Configure, don't code (JSON-based behavior)
  • Validate aggressively (helpful errors)
  • Document everything (one guide per block)
  • Start small, scale progressively (5 → 26 blocks)

When This Works:

  • Developer team available (React/TypeScript)
  • Design system exists
  • Performance matters
  • Multiple sites need shared components
  • Content team willing to learn (2-hour training)

When WordPress Is Better:

  • Non-technical team, no developer
  • Need visual WYSIWYG
  • Simple blog or brochure site
  • Need quick launch

Tech Stack:

Ready to Build Something Exceptional?

Let's turn your idea into reality. Whether you need a fractional developer for ongoing work or want to discuss a specific project, I'm here to help.

20+
Years Experience
150K+
Websites Powered
2
Successful Exits
7x
Faster with AI