Mahamudul Hasan Rubel
HomeBlogCoursesAboutProjectsSkillsExperiencePhotosContact
Mahamudul Hasan Rubel

Senior Software Engineer crafting high-performance web applications and SaaS platforms.

Navigation

  • Home
  • Blog
  • Courses
  • About
  • Projects
  • Skills
  • Experience
  • Photos
  • Contact

Get in Touch

Available for senior/lead roles and consulting.

bd.mhrubel@gmail.comHire Me

Subscribe to the newsletter

Get new articles and course lessons delivered to your inbox. No spam, unsubscribe anytime.

© 2026 Mahamudul Hasan Rubel. All rights reserved.

Built with using Next.js 16 & Tailwind v4

Back to Blog
Lesson 20 of the Advanced WordPress Plugin Engineering: Scale, Security & React UIs course
WordPressJune 27, 20263 min read

InnerBlocks and Nested Structures: Advanced Gutenberg Block Development

Master InnerBlocks in Gutenberg. Learn how to nest blocks, restrict child types, and enforce templates to build complex layouts for your WordPress plugin.

GutenbergWordPressInnerBlocksReactBlock Developmentphpplugin-development

Previously in this course, we covered the foundational aspects of Block API v2 Essentials: Metadata, React Edits, and SSR and how to manage global state using State Management with @wordpress/data: Building Scalable Stores. Building on that knowledge, this lesson focuses on creating complex, hierarchical layouts using InnerBlocks.

For our Knowledge Base plugin, we need a "Documentation Section" block that acts as a container for specific instructional components. Simple blocks aren't enough; we need a nested structure that enforces consistency.

Understanding InnerBlocks from First Principles

In Gutenberg, InnerBlocks is a specialized React component that allows a block to contain other blocks. Think of it as a "drop zone" within your component. When you use InnerBlocks, you aren't just creating a wrapper; you are defining a recursive architecture where the parent block manages the layout, and the children manage the content.

The primary power of InnerBlocks lies in two areas:

  1. Template Enforcement: You can force specific blocks to appear by default inside your container.
  2. Constraint Management: You can whitelist or blacklist which blocks a user is allowed to insert.

Worked Example: The Knowledge Base Section Block

We want to build a <kb-section> block that always contains a header and a list of step-by-step instructions. We will restrict the contents so users can only add our custom kb-step blocks or standard paragraph blocks.

1. Defining the Block Metadata

In your block.json, you must set supports to allow nesting:

JSON
{
    "name": "kb/section",
    "title": "Knowledge Base Section",
    "category": "kb-blocks",
    "supports": {
        "innerBlocks": true
    }
}

2. Implementing the Edit Component

In your edit.js, import InnerBlocks from @wordpress/block-editor. We will define a TEMPLATE constant to pre-populate the container.

JAVASCRIPT
import { InnerBlocks, useBlockProps } from CE9178">'@wordpress/block-editor';

const TEMPLATE = [
    [CE9178">'core/heading', { level: 3, placeholder: CE9178">'Section Title...' }],
    [CE9178">'kb/step', { placeholder: CE9178">'Enter step detail...' }]
];

const ALLOWED_BLOCKS = [CE9178">'core/heading', CE9178">'core/paragraph', CE9178">'kb/step'];

export default function Edit() {
    const blockProps = useBlockProps();

    return (
        <div {...blockProps}>
            <InnerBlocks
                allowedBlocks={ALLOWED_BLOCKS}
                template={TEMPLATE}
                templateLock={false} 
            />
        </div>
    );
}

3. The Save Component

The save function is straightforward. It must output the <InnerBlocks.Content /> component to ensure the nested blocks are rendered correctly in the frontend.

JAVASCRIPT
import { InnerBlocks, useBlockProps } from CE9178">'@wordpress/block-editor';

export default function Save() {
    const blockProps = useBlockProps.save();
    return (
        <div {...blockProps}>
            <InnerBlocks.Content />
        </div>
    );
}

Advanced Configuration: Template Locking

In the example above, templateLock is set to false, allowing users to add or remove blocks. If you are building a rigid UI component, you can use:

  • 'all': Users cannot move, remove, or insert new blocks.
  • 'insert': Users can move or delete blocks, but cannot insert new ones.

Hands-on Exercise

In your current Knowledge Base plugin project, refactor your main "Documentation" block to use InnerBlocks.

  1. Create a TEMPLATE that includes a core/columns block to force a side-by-side layout for large screens.
  2. Set allowedBlocks to only permit core/paragraph and core/image inside those columns.
  3. Verify that the block renders correctly by switching between the visual editor and the code editor to inspect the <!-- wp:innerblocks --> comments.

Common Pitfalls

  • Missing InnerBlocks.Content in Save: If you omit this in the save function, the nested blocks will exist in the database but will not render on the frontend.
  • Over-Restricting: Setting templateLock to 'all' too aggressively can frustrate users. Use it only when the block structure is strictly functional (e.g., a tabbed interface).
  • Missing Block Dependencies: If your allowedBlocks references a custom block, ensure that the custom block is registered before the parent block, otherwise the editor will fail to render the inner blocks correctly.

Recap

We’ve moved from simple block registration to complex, nested architectures. By utilizing InnerBlocks, allowedBlocks, and template definitions, you ensure that your Knowledge Base plugin provides a structured, predictable authoring experience while maintaining the flexibility of the Gutenberg editor. These nested structures are the backbone of professional-grade WordPress page builders and specialized plugin UIs.

Up next: We will connect our nested blocks to the database by implementing Custom REST API Integration to fetch and save live Knowledge Base data.

Previous lessonBlock API v2 EssentialsNext lesson Custom REST API Integration
Back to Blog

Similar Posts

WordPressJune 28, 20264 min read

Advanced State Persistence: Syncing Redux with localStorage

Learn to persist Gutenberg state using Redux middleware. We’ll show you how to sync editor data to localStorage for a seamless, high-performance experience.

Read more
WordPressJune 28, 20264 min read

Block Transforms and Deprecation: Managing Gutenberg Versioning

Master Gutenberg block evolution. Learn to implement block transforms and deprecation handlers to ensure seamless backward compatibility for your plugin.

Part of the course

Advanced WordPress Plugin Engineering: Scale, Security & React UIs

advanced · Lesson 20 of 56

  1. 1

    Modern PHP Standards for WordPress

    3 min
  2. 2

    Dependency Injection Basics

    3 min
  3. 3

    Architecting Service Providers

    3 min
Read more
WordPressJune 28, 20263 min read

Custom Gutenberg Block Controls: InspectorControls and State Sync

Master Gutenberg block controls by using InspectorControls, custom React inputs, and precise attribute synchronization to build professional editor experiences.

Read more
  • 4

    Advanced Custom Database Tables

    4 min
  • 5

    Data Access Objects Pattern

    3 min
  • 6

    Query Caching Strategies

    4 min
  • 7

    Database Indexing for Scale

    4 min
  • 8

    Sanitization Pipelines

    3 min
  • 9

    Output Escaping Patterns

    4 min
  • 10

    Nonce Management Architecture

    3 min
  • 11

    Capability and Permission Systems

    3 min
  • 12

    Preventing SQL Injection

    4 min
  • 13

    Secure REST API Endpoints

    3 min
  • 14

    Cross-Site Scripting Mitigation

    4 min
  • 15

    Auditing Plugin Security

    4 min
  • 16

    Modern Build Tooling with Vite

    3 min
  • 17

    React Component Architecture

    3 min
  • 18

    State Management with @wordpress/data

    3 min
  • 19

    Block API v2 Essentials

    3 min
  • 20

    InnerBlocks and Nested Structures

    3 min
  • 21

    Custom REST API Integration

    3 min
  • 22

    Optimizing React Rendering

    4 min
  • 23

    Code Splitting and Lazy Loading

    4 min
  • 24

    Advanced Admin Dashboards

    4 min
  • 25

    Component Library Design

    3 min
  • 26

    Linting and Code Quality

    3 min
  • 27

    Unit Testing with PHPUnit

    4 min
  • 28

    Integration Testing

    3 min
  • 29

    Test-Driven Development Workflow

    4 min
  • 30

    Automated CI/CD Pipelines

    3 min
  • 31

    Versioning and Release Management

    3 min
  • 32

    Internationalization (i18n)

    3 min
  • 33

    Licensing Infrastructure

    4 min
  • 34

    Automated Update API

    3 min
  • 35

    Documentation Systems

    4 min
  • 36

    Refactoring for Distribution

    4 min
  • 37

    Plugin Lifecycle Management

    3 min
  • 38

    Performance Monitoring

    3 min
  • 39

    Advanced Error Handling

    4 min
  • 40

    User Feedback Loops

    3 min
  • 41

    Handling Plugin Conflicts

    4 min
  • 42

    Advanced Hook Management

    4 min
  • 43

    Database Schema Evolution

    3 min
  • 44

    High-Concurrency Data Handling

    4 min
  • 45

    Object-Relational Mapping (ORM) Lite

    3 min
  • 46

    Advanced Query Filters

    4 min
  • 47

    Secure File Handling

    3 min
  • 48

    Background Processing

    4 min
  • 49

    Transient Caching Patterns

    4 min
  • 50

    Advanced Nonce Security

    3 min
  • 51

    Multi-tenancy Considerations

    3 min
  • 52

    Custom Gutenberg Block Controls

    3 min
  • 53

    Block Transforms and Deprecation

    4 min
  • 54

    Dynamic Block Rendering

    4 min
  • 55

    Advanced State Persistence

    4 min
  • 56

    Custom Hooks for React

    Coming soon
  • View full course