Building a Production-Ready WordPress FSE Block Theme: The Moiraine Story
Introduction: Why We Built a Custom FSE Block Theme
Over the past six months, we’ve been on an intensive journey developing Moiraine, a production-ready Full Site Editing (FSE) block theme for WordPress. This wasn’t just another theme project—it was a deep dive into modern WordPress development, performance optimization, and the Block Editor ecosystem.
At Imagewize, we’ve been building custom WordPress websites for SMEs across the US and Europe for years. But as WordPress evolved from the Classic Editor to the Block Editor (Gutenberg), and finally to Full Site Editing, we realized we needed a theme that could:
- Deliver blazing-fast performance without expensive page builders
- Provide design flexibility through reusable block patterns
- Meet WordPress.org Theme Review requirements for quality and accessibility
- Support modern development workflows with theme.json and minimal CSS
This post shares what we learned building Moiraine from the ground up—the technical architecture, performance optimizations, accessibility improvements, and the WordPress.org submission process.
What is Full Site Editing (FSE)?
Before diving into the build process, let’s clarify what Full Site Editing actually means in 2026.
The Evolution of WordPress Theming
Classic Themes (Pre-2018):
- PHP template files (header.php, footer.php, single.php)
- Functions.php for customization
- Limited visual editing
- Required coding knowledge for layout changes
Block Editor Themes (2018-2021):
- Introduction of Gutenberg block editor
- Content editing with blocks
- Templates still PHP-based
- Hybrid approach
Full Site Editing Themes (2021-Present):
- HTML template files instead of PHP
- Visual editing of headers, footers, and templates
- Global Styles via theme.json
- Block patterns for reusable layouts
- Complete design control without code
Why FSE Matters for Modern Web Development
FSE represents a fundamental shift in how WordPress sites are built:
- Performance: No heavy page builders (eliminates 500KB+ of JavaScript/CSS)
- Maintainability: Standardized block-based architecture
- Client Empowerability: Non-technical users can edit entire sites visually
- Developer Efficiency: Reusable patterns and centralized theme.json configuration
- Future-Proof: WordPress core development is fully committed to FSE
The Moiraine Architecture
Moiraine is built on a foundation of modern WordPress best practices. Here’s the core structure:
Theme Structure
moiraine/
├── assets/
│ └── fonts/ # Self-hosted variable fonts
│ ├── mona-sans/ # Primary font family
│ ├── bodoni-moda/ # Serif option
│ └── Open-Sans.woff2 # Body text
├── patterns/ # 108 block patterns
│ ├── hero-*.php
│ ├── card-*.php
│ ├── testimonial-*.php
│ ├── pricing-*.php
│ └── template-*.php
├── parts/ # 7 template parts
│ ├── header.html
│ ├── footer.html
│ └── sidebar.html
├── styles/ # Style variations
│ ├── colors/ # 10 color schemes
│ ├── typography/ # 10 font pairings
│ └── [variations].json # 6 complete variations
├── templates/ # 8 HTML templates
│ ├── index.html
│ ├── single.html
│ └── page.html
├── functions.php # Minimal setup
├── theme.json # Core configuration
└── style.css # Theme metadata + reset
Key Design Decisions
1. theme.json as Single Source of Truth
Rather than scattering styles across multiple CSS files, we centralized configuration in theme.json:
- Color palette: 11 semantic colors (primary, base, contrast, borders)
- Typography: 7 fluid font sizes with min/max responsive scaling
- Spacing: 7 preset spacing scales using clamp() for fluid sizing
- Shadows: 8 shadow presets (4 dark, 4 light variants)
- Custom properties: Font weights, line heights, layout widths
This approach reduces CSS bloat and ensures consistency across all blocks and patterns.
2. Variable Font Implementation
We implemented Mona Sans, a variable font that supports:
- Font weight range: 300-900
- Font stretch: 75%-125%
- Single WOFF2 file for all weights and widths
This replaced traditional font loading that would require 10+ font files, reducing HTTP requests and improving performance.
3. Fluid Typography and Spacing
Every font size and spacing value uses CSS clamp() for truly responsive design:
{
"fontSize": {
"fluid": {
"min": "1.5rem",
"max": "2.75rem"
},
"size": "2.75rem",
"slug": "large"
}
}
This eliminates the need for media query breakpoints—text scales smoothly from mobile to desktop.
Building 108+ Block Patterns
Block patterns are Moiraine’s superpower. They’re pre-designed block layouts that users can insert with a single click.
Pattern Categories We Built
- Hero Sections (8 patterns)
- Call-to-action with buttons
- Text and image combinations
- Large text hero variations
- Card Layouts (12 patterns)
- Blog post cards
- Pricing tables
- Contact cards
- Call-to-action cards
- Testimonials (6 patterns)
- With social links
- With large quotes
- Logo grids with testimonials
- Features & Benefits (8 patterns)
- Icon boxes
- Number statistics
- Text and image columns
- Pricing Tables (4 patterns)
- 2-column and 3-column layouts
- Feature comparison grids
- Full Page Templates (7 patterns)
- Blog archive pages
- Contact pages
- Pricing pages
- 404 error pages
- Headers & Footers (15 patterns)
- Dark and light variations
- Mobile menu patterns
- Mega menu integration
Pattern Development Workflow
Each pattern is a PHP file that registers block markup:
<?php
/**
* Title: Hero Call to Action with Buttons
* Slug: moiraine/hero-call-to-action-buttons
* Categories: moiraine-hero
* Viewport Width: 1280
*/
?>
<!-- wp:group -->
<div class="wp-block-group">
<!-- Block markup here -->
</div>
<!-- /wp:group -->
Pattern Development Tips:
- Use semantic color names (primary, base, contrast) not hex codes
- Reference preset spacing values from theme.json
- Avoid hardcoded font sizes—use preset slugs
- Test patterns at mobile and desktop widths
- Include viewport width for accurate pattern previews
Custom Block Development: The Moiraine Blocks Plugin
WordPress.org Theme Review guidelines prohibit themes from registering custom blocks. This makes sense—blocks should be portable between themes.
We created the Moiraine Blocks companion plugin with three custom blocks:
1. Mega Menu Block
Purpose: Advanced navigation with dropdown panels and template part integration.
Technical Implementation:
- Built with
@wordpress/scriptsbuild tooling - Uses WordPress Interactivity API for dropdown behavior
- Supports template parts for mega menu content
- Keyboard navigation compliant (ARIA patterns)
- Mobile-responsive with touch/swipe support
Why We Built It:
Standard WordPress navigation blocks don’t support complex mega menus with multi-column layouts, images, and rich content. Our mega menu block lets users:
- Insert any template part as a dropdown panel
- Create product showcases in navigation
- Build feature-rich menus without custom code
2. Carousel Block
Purpose: Responsive image/content slider with Slick Carousel integration.
Technical Implementation:
- Parent block that wraps multiple slides
- Slick Carousel library for slide functionality
- Customizable settings (autoplay, arrows, dots, speed)
- Responsive breakpoints for mobile/tablet/desktop
Use Cases:
- Client testimonial carousels
- Portfolio/case study showcases
- Product image galleries
- Logo sliders
3. Slide Block
Purpose: Individual carousel slides with InnerBlocks support.
Technical Implementation:
- Uses WordPress InnerBlocks API
- Allows any block combination inside slides
- Seamless integration with parent Carousel block
Flexibility:
Users can build slides with any combination of:
- Images, headings, paragraphs
- Buttons and call-to-actions
- Testimonials with attribution
- Custom HTML or embeds
theme.json: The Heart of Modern WordPress Themes
The 927-line theme.json file is Moiraine’s configuration center. Let’s break down the key sections:
Settings Section
Defines available design tools and options:
{
"settings": {
"appearanceTools": true,
"color": {
"defaultPalette": false,
"palette": [
{
"name": "Brand",
"slug": "primary",
"color": "#5344F4"
}
]
},
"typography": {
"fluid": true,
"fontFamilies": [...]
},
"spacing": {
"spacingSizes": [...]
}
}
}
Key Configuration Decisions:
defaultPalette: false— Removes WordPress default colors for cleaner interfacedefaultGradients: false— Custom gradients onlyfluid: true— Enables fluid typography scalinguseRootPaddingAwareAlignments: true— Better full-width alignment
Styles Section
Applies default styles to blocks and elements:
{
"styles": {
"elements": {
"button": {
"border": {
"radius": "5px"
},
"color": {
"background": "var:preset|color|main",
"text": "var:preset|color|base"
},
"typography": {
"fontSize": "var:preset|font-size|small",
"fontWeight": "500"
}
}
}
}
}
This eliminates the need for custom CSS—buttons automatically get consistent styling across the entire site.
Block-Specific Styles
We customized 20+ core blocks directly in theme.json:
- Navigation: Link hover effects, font weight
- Quote/Pullquote: Border styles, citation formatting
- Code/Preformatted: Background colors, padding, monospace font
- Comments: Author name, date, reply link styling
- Post Template: Heading sizes in loops
Custom Templates and Template Parts
theme.json also registers available templates and their purposes:
{
"customTemplates": [
{
"name": "page-no-title",
"title": "Page (Full Width, No Title)",
"postTypes": ["page", "post"]
}
],
"templateParts": [
{
"name": "header",
"area": "header"
}
]
}
Performance Optimization Strategies
Moiraine was built with performance as a primary goal. Here’s what we implemented:
1. Zero Page Builder Bloat
Problem: Page builders like Elementor or WPBakery add 500KB-2MB of assets.
Solution: FSE blocks are native to WordPress core—no additional JavaScript framework needed.
Result: Moiraine adds only ~25KB of CSS (including reset and custom styles).
2. Self-Hosted Variable Fonts
Problem: Google Fonts requires external HTTP requests and privacy concerns (GDPR).
Solution: Self-hosted WOFF2 variable fonts with font-display: block/swap.
Result:
- Zero external font requests
- Single font file loads all weights (300-900)
- Font subsetting reduces file size by 60%
3. Minimal JavaScript Usage
JavaScript Loaded:
- WordPress core blocks: ~85KB (gzipped)
- Mega Menu Interactivity API: ~8KB
- Slick Carousel (when carousel block used): ~15KB
JavaScript NOT Loaded:
- jQuery (not used anywhere)
- Animation libraries
- Page builder frameworks
4. CSS Architecture
style.css contains only:
- CSS reset (normalize.css approach)
- Form standardization
- Accessibility enhancements
- Mobile responsive helpers
All design styles come from theme.json, which WordPress converts to inline CSS on page load—highly optimized and cacheable.
5. Image Optimization Ready
Moiraine fully supports WordPress 5.5+ features:
- Lazy loading (native)
- WebP image format
- Responsive image srcset
- Aspect ratio preservation
Need help with WordPress speed optimization? We offer professional performance optimization services for SMEs.
Accessibility: Building for Everyone
Accessibility was non-negotiable. We implemented WCAG 2.1 AA standards throughout.
Keyboard Navigation
Navigation Menus:
- Full keyboard support (Tab, Enter, Escape, Arrow keys)
- ARIA attributes for screen readers
- Focus visible states on all interactive elements
Mega Menu Accessibility:
.skip-link:focus {
background-color: var(--wp--preset--color--primary);
outline: 3px solid var(--wp--preset--color--main);
z-index: 100000;
/* Visible skip link on keyboard focus */
}
Color Contrast
All color combinations tested for WCAG AA contrast ratios:
- Text on backgrounds: Minimum 4.5:1
- Large text: Minimum 3:1
- Buttons and interactive elements: 4.5:1
Semantic HTML
- Proper heading hierarchy (h1 → h6)
- Landmark regions (header, nav, main, footer)
- Form labels associated with inputs
- Alt text requirements for images
Screen Reader Optimization
- Skip to content links
- ARIA labels on icon-only buttons
- Focus management in modals/dropdowns
- Descriptive link text (no “click here”)
WordPress.org Theme Submission Process
Submitting to the WordPress.org Theme Directory was an intensive learning experience. Here’s what we went through:
Pre-Submission Requirements
Theme Check Plugin: Must pass all required checks
- No PHP errors or warnings
- Proper text domain usage
- Required theme files present
- Security best practices (escaping, sanitization)
Theme Unit Test: Import and test with sample content
- All post formats display correctly
- Comments system works
- Pagination functions
- Archive pages render properly
Accessibility Audit:
- Keyboard navigation works everywhere
- Color contrast meets WCAG AA
- Skip links functional
- Screen reader friendly
Initial Submission Feedback
Our first submission received detailed feedback on:
- Documentation Requirements
- Added comprehensive README.md
- Created screenshot.png showing theme design
- Documented all third-party resources
- Code Quality Issues
- Fixed variable naming conventions
- Removed unused functions
- Improved inline documentation
- Licensing Clarity
- Listed all font licenses (SIL Open Font License)
- Documented image sources
- Added GPL license headers
- Security Hardening
- Escaped all output (esc_html, esc_url, esc_attr)
- Sanitized inputs
- Used nonces for form submissions
Iterative Review Rounds
Round 1: Documentation and licensing issues
Round 2: Accessibility improvements needed
Round 3: Code cleanup and best practices
Round 4: Final security review
Round 5: Approval!
Timeline: ~6 weeks from initial submission to approval
Lessons Learned
- Start with Theme Check plugin early — don’t wait until submission
- Test with Theme Unit Test data — reveals edge cases
- Document everything — licenses, credits, resources
- Follow WordPress Coding Standards — use PHP_CodeSniffer
- Accessibility is non-negotiable — test with keyboard and screen readers
Style Variations: Design Flexibility at Scale
Moiraine includes 6 complete style variations and dozens of mix-and-match options:
Complete Style Variations
- Default (Moiraine) — Purple brand, modern sans-serif
- Agency — Bold typography, high contrast
- Consulting — Professional blue, Bodoni serif headings
- Creator — Vibrant pink accent, wide headings
- Publisher — Editorial style, optimized for reading
- Startup — Energetic orange, condensed fonts
- Studio — Minimalist, narrow typography
Mix-and-Match Options
Color Schemes (10):
- Blue, Royal Blue, Teal, Green
- Pink, Red, Orange, Neon
- Corporate Blue, Publisher
Typography Presets (10):
- Various font pairings
- Sans-serif and serif combinations
- Condensed, narrow, expanded variations
How It Works:
Each variation is a separate theme.json file that overrides specific settings:
{
"version": 3,
"title": "Consulting",
"settings": {
"color": {
"palette": [
{
"slug": "primary",
"color": "#1E3A8A",
"name": "Professional Blue"
}
]
}
}
}
Users can activate variations from Appearance → Editor → Styles, switching entire site designs with one click.
Real-World Performance Metrics
We deployed Moiraine on demo.imagewize.com. Here are the results:
PageSpeed Insights (Mobile)
- Performance: 95-98/100
- First Contentful Paint: 0.8s
- Largest Contentful Paint: 1.2s
- Total Blocking Time: 0ms
- Cumulative Layout Shift: 0.01
Lighthouse Scores
- Performance: 98/100
- Accessibility: 100/100
- Best Practices: 100/100
- SEO: 100/100
Asset Size Analysis
Total Page Weight (Homepage):
- HTML: 18KB
- CSS: 28KB (inline from theme.json)
- JavaScript: 92KB (WordPress core blocks)
- Fonts: 68KB (variable WOFF2)
- Images: 145KB (WebP, optimized)
Total: ~351KB (fully loaded homepage)
Compare to typical page builder sites: 2-5MB
Development Workflow and Tools
Local Development Environment
Trellis (Lima-based VM):
- Ubuntu 24.04 LTS
- PHP 8.3
- MariaDB 10.6
- Nginx web server
Access:
cd ~/code/imagewize.com/trellis
trellis vm shell
Build Tools
Block Development:
cd blocks/mega-menu
npm install
npm run build # Production build
npm run start # Development watch mode
Theme Development:
- No build process needed for theme.json
- CSS is minimal and hand-written
- Patterns are pure PHP
Version Control Strategy
Git Workflow:
mainbranch: Production-ready releasesdevelopbranch: Active development- Feature branches: New patterns or features
- Pull request reviews before merging
Testing Protocol
Pre-Release Checklist:
- [ ] Theme Check plugin passes
- [ ] Theme Unit Test import works
- [ ] Accessibility audit (keyboard, screen reader)
- [ ] Browser testing (Chrome, Firefox, Safari, Edge)
- [ ] Mobile responsive testing
- [ ] PageSpeed Insights > 90
- [ ] Code linting (PHPCS with WordPress standards)
Key Takeaways for WordPress Developers
After six months of intensive FSE theme development, here are our biggest lessons:
1. theme.json is a Game-Changer
Centralizing all design configuration eliminates CSS maintenance nightmares. Every color, font size, and spacing value comes from a single source.
Benefit: Changing brand colors site-wide is a 2-minute edit, not a 2-hour CSS hunt.
2. Block Patterns > Custom Post Types
Instead of building custom post types for testimonials, team members, or services, use block patterns. They’re more flexible and user-friendly.
Benefit: Users can customize pattern layouts without touching code.
3. Variable Fonts are Production-Ready
Variable fonts reduce HTTP requests, improve performance, and provide infinite design flexibility.
Benefit: One 68KB file replaces 10+ individual font files.
4. FSE Themes Require Different Thinking
Stop thinking in PHP templates. Start thinking in reusable block compositions and visual editing experiences.
Mindshift: “How can I build this so a non-technical user can edit it?”
5. Accessibility Must Be Built In, Not Bolted On
Retrofitting accessibility is painful. Build with semantic HTML, keyboard navigation, and ARIA from day one.
Benefit: Pass WordPress.org review faster and serve all users equally.
6. Performance is a Feature
Clients notice when their site loads in under 1 second. FSE themes can achieve this without sacrificing design flexibility.
Competitive Advantage: Moiraine sites consistently score 95+ on PageSpeed Insights.
What’s Next for Moiraine
Our roadmap for continued development:
Planned Features
Q1 2026:
- Additional mega menu layouts
- WooCommerce integration patterns
- E-commerce product showcase blocks
Q2 2026:
- Animation controls (scroll reveals, fade-ins)
- Advanced grid layout patterns
- Form styling variations
Q3 2026:
- Additional style variations
- Dark mode toggle option
- Extended typography presets
Community Contributions
Moiraine is open source (GPL v3). We welcome:
- Pattern contributions
- Style variation submissions
- Bug reports and fixes
- Translation contributions
GitHub: github.com/imagewize/moiraine
WordPress.org: wordpress.org/themes/moiraine
Conclusion: FSE is the Future of WordPress
Building Moiraine taught us that Full Site Editing isn’t just a new feature—it’s a fundamental shift in WordPress development philosophy.
For Developers:
- Faster theme development
- Less CSS to maintain
- Standardized architecture
- Better performance out of the box
For Clients:
- Visual editing everywhere
- No expensive page builder subscriptions
- Faster websites
- More design flexibility
For End Users:
- Easier content editing
- Consistent design system
- Accessible by default
- Future-proof platform
If you’re still building WordPress sites with Classic themes or heavy page builders, 2025 is the year to embrace FSE. The tooling is mature, the performance benefits are real, and the WordPress community is all-in on this direction.
Get Started with Moiraine
Try the Theme:
- Download from WordPress.org Theme Directory
- View demo at demo.imagewize.com
- Explore pattern library and style variations
Learn More:
Need Custom WordPress Development?
We specialize in custom WordPress theme development and performance optimization for SMEs across the US and Europe. Contact us to discuss your project.
About the Author:
Jasper Frumau is a WordPress developer specializing in performance optimization, FSE theme development, and Trellis hosting for SMEs across the US and Europe. He builds fast, accessible WordPress sites at Imagewize.
WordPress Block Editor Resources
Official Documentation:
Community Resources:
Development Tools:
- @wordpress/scripts — Block build tooling
- Theme Check Plugin — Pre-submission testing
- Query Monitor — Performance debugging