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.
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:
- Template Enforcement: You can force specific blocks to appear by default inside your container.
- 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.
JAVASCRIPTimport { 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.
JAVASCRIPTimport { 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.
- Create a
TEMPLATEthat includes acore/columnsblock to force a side-by-side layout for large screens. - Set
allowedBlocksto only permitcore/paragraphandcore/imageinside those columns. - 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.Contentin Save: If you omit this in thesavefunction, the nested blocks will exist in the database but will not render on the frontend. - Over-Restricting: Setting
templateLockto'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
allowedBlocksreferences 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.
Work with me

Custom WordPress Plugin Development
Custom WordPress & WooCommerce plugins built to standard — by the developer behind a plugin with 5,000+ active installs and a SaaS with 10,000+ users.

Custom WordPress Theme Development
A custom WordPress theme built exactly to your design — fast, clean, and easy to manage. No bloated page builders, no compromises.