Skip to main content
This document outlines the key architectural decisions and design principles that guide the Gutenberg project. Understanding these principles will help you make implementation decisions that align with the project’s architecture.

Package Layering

Gutenberg follows a strict three-layer architecture for editor packages:

Layer Hierarchy

  1. @wordpress/block-editor (Bottom Layer)
    • Generic, WordPress-agnostic block editor
    • No WordPress-specific dependencies
    • Can be used in any application
  2. @wordpress/editor (Middle Layer)
    • WordPress post-type-aware functionality
    • Depends on @wordpress/block-editor
    • Handles WordPress entities (posts, pages)
  3. @wordpress/edit-post / @wordpress/edit-site (Top Layer)
    • Complete editor screens
    • Depends on @wordpress/editor and @wordpress/block-editor
    • Full WordPress integration

Critical Rule

Lower layers MUST NOT depend on higher layers. This ensures:
  • Code reusability
  • Clear separation of concerns
  • WordPress-agnostic editor core
Example Violations to Avoid:
Correct Approach:

Block Data Model

Understand how blocks are represented and manipulated:

In-Memory Structure

During editing, blocks exist as in-memory tree structures:

Serialized Format

Blocks are saved as HTML with comment delimiters:

Key Principle

Always work with the block tree via APIs, not the serialized HTML.

Data Layer Architecture

Gutenberg uses @wordpress/data for state management, following a Redux-like pattern.

State Management Principles

Use data stores for all state:

Critical Rules

Edit entities through core-data actions:
Don’t mutate state directly:

Styles System

Gutenberg’s styling follows a three-layer merge system:

Style Layer Hierarchy

  1. WordPress Defaults (Base)
    • Core WordPress styles
    • Block default styles
  2. theme.json (Theme Layer)
    • Theme-defined styles and settings
    • Global style variations
  3. User Preferences (Top Layer)
    • User customizations
    • Site-specific overrides
Each layer overrides the previous, creating a cascade.

Implementation Guidelines

Use Block Supports API:
Use CSS Custom Properties:
Respect theme.json settings:

Modularity and Distribution

Gutenberg packages work in multiple contexts:

Dual Distribution

Production packages are available as:
  1. npm packages: @wordpress/components
    • Used by third-party developers
    • Bundled into plugins and themes
  2. WordPress scripts: wp-components
    • Loaded via wp_enqueue_script()
    • Available as global wp.components

Critical Requirement

Production packages must work in both contexts.

WordPress-Agnostic Core

The @wordpress/block-editor package is designed to be WordPress-agnostic:

What This Means

No WordPress-specific dependencies:
Generic, reusable components:

Development Tools Separation

The @wordpress/scripts package has special constraints:

Special Case: @wordpress/scripts

Purpose: Generic build tool for:
  • Gutenberg plugin development
  • WordPress Core contributions
  • Third-party plugin development
Critical Rule: Avoid Gutenberg-specific changes in @wordpress/scripts

Key Takeaways

When contributing to Gutenberg:
  1. Respect package layering - Lower layers don’t depend on higher layers
  2. Use block APIs - Don’t manipulate serialized HTML directly
  3. Use data stores - Follow Redux patterns via @wordpress/data
  4. Use CSS custom properties - Don’t hardcode style values
  5. Keep block-editor agnostic - No core-data or WordPress-specific code
  6. Make packages portable - Work in both npm and WordPress contexts
  7. Keep build tools generic - @wordpress/scripts serves multiple use cases

Further Reading

For detailed architecture documentation:

Next Steps