Summary
This proposal introduces a feature-based block architecture inside theme-elementary to support scalable development of custom client blocks, while preserving the theme’s identity as a clean Full Site Editing (FSE) starter.
The goal is not to introduce a framework or PHP component system, but to improve internal organization so that custom blocks can grow in a structured and maintainable way across projects.
🎯 Problem Statement
theme-elementary currently organizes assets by file type:
assets/src/css
assets/src/js
This works for small themes. However, in client projects we typically:
- Add multiple custom blocks
- Add block-specific JS functionality
- Add block-specific CSS
- Sometimes introduce server-side rendering
- Add custom integrations (e.g., WooCommerce, dynamic data)
A block with custom JS, scoped CSS, and a render callback may require touching multiple directories. As the number of blocks grows, this increases:
- Risk of mismatched or orphaned files
- Duplication of logic
- Maintenance complexity
- Contributor cognitive load
We need scalable structure without turning the starter into a framework.
🧩 Proposed Architecture (Block-First)
Introduce a feature-based block structure inside assets/src:
.
├── assets
│ ├── build
│ └── src
│ ├── blocks
│ │ ├── example-block
│ │ │ ├── block.json
│ │ │ ├── edit.js
│ │ │ ├── save.js
│ │ │ ├── editor.css (optional)
│ │ │ ├── style.css
│ │ │ └── render.php (optional)
│ │ └── another-block
│ │ ├── ...
│ │
│ ├── components
│ ├── css (global styles)
│ └── js (global scripts)
│
├── inc
├── parts
├── patterns
├── templates
├── theme.json
🧠 Architectural Principles
1️⃣ Block-First, Not Framework-First
- Each custom block lives in its own folder.
- Blocks remain fully compliant with
block.json.
- No custom PHP view-layer abstraction is introduced.
- No component rendering framework is added.
2️⃣ render.php Decision Rule
Use render.php when block output depends on server-side data such as:
- Post meta
- WooCommerce data
- Dynamic queries
- Context-dependent rendering
If the block is static and fully defined by editor attributes, use save.js.
3️⃣ Component Promotion Rule
The /components directory is reserved for shared JS utilities only.
Rule:
- If logic is used by only one block → keep it inside that block’s folder.
- If logic is used by two or more blocks → move it to
/components.
No PHP view components are introduced in the starter.
4️⃣ Preserve FSE Compatibility
This proposal does not:
- Modify template parts
- Change patterns structure
- Alter
theme.json
- Introduce external frameworks
- Change asset registration behavior
- Replace WordPress block philosophy
The theme remains a clean FSE starter.
🛠 Build Tooling
This architecture operates within the existing build pipeline (e.g., @wordpress/scripts).
Block assets are discovered and compiled via block.json fields such as:
editorScript
script
style
editorStyle
Nested block folders are fully supported by this mechanism.
Phase 1 does not:
- Modify asset output paths
- Change block registration behavior
- Introduce new runtime dependencies
Build behavior remains unchanged.
🪜 Implementation Plan
Phase 1 — Introduce Structure
- Add
/blocks directory inside assets/src
- Add one example block as reference
- Ensure build parity with existing setup
- No breaking changes
Phase 2 — Documentation
Add a block creation checklist covering:
- Required
block.json fields
- Naming conventions
- When to use
render.php
- When to promote shared logic to
/components
- Editor vs frontend asset separation
Phase 3 — Gradual Adoption
- All future client-specific blocks follow this structure
- Existing global CSS/JS may be refactored incrementally
📊 Success Criteria
- At least one example block implemented in the new structure
- No increase in frontend bundle size
- No regression in Global Styles behavior
- No change in FSE template behavior
- Documentation updated with clear block creation guidelines
📦 Expected Outcomes
- Clean scaling from 1 to 20+ custom blocks
- Reduced duplication across client projects
- Clear contributor rules that prevent architectural drift
⚠️ Non-Goals
- Introducing a PHP component rendering framework
- Replacing Gutenberg block system
- Converting the starter into an enterprise theme framework
- Breaking backward compatibility
If approved, Phase 1 will introduce the folder structure and a single example block to validate the approach before wider adoption.
Summary
This proposal introduces a feature-based block architecture inside
theme-elementaryto support scalable development of custom client blocks, while preserving the theme’s identity as a clean Full Site Editing (FSE) starter.The goal is not to introduce a framework or PHP component system, but to improve internal organization so that custom blocks can grow in a structured and maintainable way across projects.
🎯 Problem Statement
theme-elementarycurrently organizes assets by file type:This works for small themes. However, in client projects we typically:
A block with custom JS, scoped CSS, and a render callback may require touching multiple directories. As the number of blocks grows, this increases:
We need scalable structure without turning the starter into a framework.
🧩 Proposed Architecture (Block-First)
Introduce a feature-based block structure inside
assets/src:🧠 Architectural Principles
1️⃣ Block-First, Not Framework-First
block.json.2️⃣ render.php Decision Rule
Use
render.phpwhen block output depends on server-side data such as:If the block is static and fully defined by editor attributes, use
save.js.3️⃣ Component Promotion Rule
The
/componentsdirectory is reserved for shared JS utilities only.Rule:
/components.No PHP view components are introduced in the starter.
4️⃣ Preserve FSE Compatibility
This proposal does not:
theme.jsonThe theme remains a clean FSE starter.
🛠 Build Tooling
This architecture operates within the existing build pipeline (e.g.,
@wordpress/scripts).Block assets are discovered and compiled via
block.jsonfields such as:editorScriptscriptstyleeditorStyleNested block folders are fully supported by this mechanism.
Phase 1 does not:
Build behavior remains unchanged.
🪜 Implementation Plan
Phase 1 — Introduce Structure
/blocksdirectory insideassets/srcPhase 2 — Documentation
Add a block creation checklist covering:
block.jsonfieldsrender.php/componentsPhase 3 — Gradual Adoption
📊 Success Criteria
📦 Expected Outcomes
If approved, Phase 1 will introduce the folder structure and a single example block to validate the approach before wider adoption.