This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Elayne Blocks is a WordPress plugin providing custom Gutenberg blocks for the Elayne theme. The plugin contains three blocks: Mega Menu, Carousel, and Slide.
Requirements:
- WordPress 6.7+
- PHP 7.3+
Each block has isolated dependencies and must be built separately:
# Build all blocks
cd blocks/carousel && npm install && npm run build
cd blocks/mega-menu && npm install && npm run build
cd blocks/slide && npm install && npm run build
# Development mode (watch for changes)
cd blocks/[block-name] && npm start
# Linting
npm run lint:js # JavaScript linting
npm run lint:css # CSS linting
npm run format # Format codeImportant: The mega-menu block uses --experimental-modules flag for its build/start commands.
The plugin uses dynamic block discovery (elayne-blocks.php:31-55). At runtime:
- Scans
/blocksdirectory duringinitaction - Looks for
build/block.jsonin each subdirectory - Auto-registers all discovered blocks via
register_block_type()
This means blocks are auto-discovered - no manual registration needed when adding new blocks.
Each block follows this structure:
blocks/[block-name]/
├── src/
│ ├── block.json # Block metadata (single source of truth)
│ ├── index.js # Registration entry point
│ ├── edit.js # React editor component
│ ├── save.jsx/.js # Frontend output markup
│ ├── view.js # Frontend interactivity (optional)
│ ├── render.php # Server-side rendering (optional)
│ ├── editor.scss # Editor-only styles
│ └── style.scss # Frontend + editor styles
├── build/ # wp-scripts output (committed for Packagist)
├── package.json
└── node_modules/
Carousel → Slide Hierarchy:
- Carousel (elayne/carousel) only allows Slide (elayne/slide) children
- Slide can only exist inside Carousel (enforced via
parentconstraint in block.json) - Slide uses InnerBlocks to accept any block content
Carousel Advanced Features:
- Toolbar Controls: Quick-access buttons for Center Mode, Thumbnail Navigation, and Variable Width
- Thumbnail Navigation: Synced secondary carousel with image thumbnails (supports 4 positions: below/above/left/right)
- Center Mode: Active slide centered with partial view of adjacent slides (peek effect)
- Variable Width: Slides can have different widths based on content
- Lazy Loading: On-demand or progressive image loading for performance
- Adaptive Height: Auto-adjusts carousel height to match active slide
- Organized Sidebar: Settings grouped into Layout, Behavior, Navigation, Responsive, Colors, and Advanced panels
Mega Menu:
- Can only be placed inside
core/navigationorelayne/nav-builderblocks - Template Part-Based Content System:
- Uses WordPress Template Parts for mega menu content (no InnerBlocks)
- Template parts stored in
/partsdirectory and registered viaget_block_templatesfilter - Content edited naturally in Site Editor via template part selection
- Includes 6 ready-to-use template parts (simple-list, three-column, icon-grid, featured-content, image-links, footer-style)
- Requires theme integration: The Elayne theme must register the 'menu' template part area via
default_wp_template_part_areasfilter for sidebar navigation to appear
- Layout Modes:
- Dropdown: Traditional dropdown menu beneath navigation item
- Overlay: Full-screen overlay covering the entire page
- Uses WordPress Interactivity API for frontend state management
- Renders via PHP template (render.php) for dynamic content
Slick Carousel assets are loaded conditionally (elayne-blocks.php:60-90):
if ( has_block( 'elayne/carousel' ) ) {
// Only enqueue when carousel block is present on page
}The mega-menu block uses the Interactivity API for frontend reactivity. Implementation is based on Human Made's HM Mega Menu Block.
Content System (Theme-Based Template Parts):
- Theme-scoped template parts - Users create template parts in the Site Editor (Appearance → Editor → Patterns → Template Parts)
- Template parts are stored in the database under the active theme's namespace
- The plugin provides patterns (not file-based template parts) that users can insert into new template parts
- Users select template parts by slug in the mega menu block settings
- Content is fully editable in the Site Editor's standard template part workflow
- No plugin-provided template part files - all content lives in the database
Required Theme Integration:
The active theme MUST register the 'menu' template part area via the default_wp_template_part_areas filter. The Elayne theme includes this by default. Other themes need to add:
add_filter( 'default_wp_template_part_areas', function( $areas ) {
$areas[] = array(
'area' => 'menu',
'label' => __( 'Menus', 'your-theme' ),
'description' => __( 'Template parts for navigation and mega menu content', 'your-theme' ),
'icon' => 'menu',
'area_tag' => 'nav',
);
return $areas;
} );Workflow:
- User creates a new template part in Site Editor with area "Menus"
- User inserts a mega menu pattern (from
patterns/mega-menu-*.php) or builds custom content - User saves the template part (e.g., slug:
mega-menu-shop) - User adds Mega Menu block to navigation and selects the template part slug
- Template part is rendered via
block_template_part( $menuSlug )with theme scope
Layout Modes:
- Dropdown: Traditional dropdown positioned beneath navigation item
- Overlay: Full-screen overlay covering entire viewport
Interactivity Structure:
src/view.js- Defines state, actions, and callbacks viastore()src/render.php- Server-side template with data attributes:data-wp-interactive- Namespacedata-wp-context- State managementdata-wp-on--click- Event handlersdata-wp-bind--*- Attribute bindings
Features:
- Click/keyboard navigation
- Outside-click dismissal
- Focus management
- Seamless template part integration
All blocks follow this pattern in src/index.js:
import { registerBlockType } from '@wordpress/blocks';
import metadata from './block.json';
import Edit from './edit';
import Save from './save';
registerBlockType(metadata.name, {
...metadata,
edit: Edit,
save: Save,
});Metadata from block.json is the single source of truth, with Edit/Save implementations added at registration time.
- Create
/blocks/newblock/directory - Add standard file structure (see Block Structure above)
- Create
src/block.jsonwith block metadata - Implement
src/index.js,src/edit.js,src/save.jsx - Add
package.jsonwith build scripts (copy from existing blocks) - Run
npm install && npm run build - Plugin auto-discovers block on next page load
CRITICAL: The mega menu block requires the active theme to register the 'menu' template part area. The Elayne theme includes this by default. Other themes must add it via functions.php:
add_filter( 'default_wp_template_part_areas', function( $areas ) {
$areas[] = array(
'area' => 'menu',
'area_tag' => 'div',
'label' => __( 'Menu', 'your-theme' ),
'description' => __( 'Template part area for mega menus', 'your-theme' ),
'icon' => 'navigation',
);
return $areas;
});Without theme registration:
- Template parts won't appear in the Site Editor's Patterns → Template Parts section
- Users cannot create or edit mega menu template parts
- The mega menu block will have no template parts to select
The Elayne theme implementation: See ~/code/imagewize.com/demo/web/app/themes/elayne - includes menu and sidebar template part areas.
elayne-blocks.php- Main plugin file with block discovery logicpatterns/- Mega menu block patterns (used to create template parts)blocks/*/src/block.json- Block metadata and configurationblocks/*/src/edit.js- Block editor interfaceblocks/*/src/save.jsx- Block frontend outputblocks/carousel/slick/- Third-party Slick Carousel library (vendored)blocks/mega-menu/README.md- Mega menu usage and integration guide
Important: When adding separator blocks to patterns, use the WordPress 6.7+ compatible format to avoid block validation errors:
✅ Correct format:
<!-- wp:separator {"className":"is-style-wide"} -->
<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide"/>
<!-- /wp:separator -->❌ Avoid (causes validation errors):
<!-- wp:separator {"className":"is-style-wide","style":{"color":{"background":"var:preset|color|contrast-2"}}} -->
<hr class="wp-block-separator has-background is-style-wide" style="background-color:var(--wp--preset--color--contrast-2);opacity:0.2"/>
<!-- /wp:separator -->The older format with inline opacity styles and custom background colors is incompatible with WordPress 6.7+ and will cause block validation errors. Use the simplified format which inherits theme colors automatically.
- Each block has isolated
node_modules(allows independent versioning) - Block names use namespace/blockname format (elayne/carousel, elayne/mega-menu)
- Attributes in block.json define all user-customizable data
- InnerBlocks pattern used for nested content (carousel/slide relationship)
- wp-scripts handles Webpack, Babel, and all build tooling
- Important:
build/directories are committed to Git for Packagist distribution so users get working blocks without needing to run build commands
IMPORTANT: Never mention AI tools (Claude, ChatGPT, etc.) in commit messages. Commit messages should be professional and focus on the changes made, not the tools used to make them.
Keep commit messages concise:
- Use short, descriptive titles (50 characters or less when possible)
- Add details in the body only when necessary
- Avoid overly verbose explanations
Good commit messages:
- "Fix carousel block initialization on frontend"
- "Add ABSPATH security check to mega-menu render.php"
- "Update text domain consistency across all blocks"
- "Add carousel block patterns"
- "Update carousel CSS for new features"
Bad commit messages:
- "Fix authentication bug (with help from Claude)" ❌
- "Claude helped me refactor the carousel code" ❌
- "Co-Authored-By: Claude Sonnet 4.5" ❌
- Overly long messages with unnecessary details ❌
When updating the plugin version, you must update three files in sync:
- CHANGELOG.md - Add new version section with changes
- readme.txt - Update
Stable tagheader and add changelog entry - elayne-blocks.php - Update
Versionin plugin header andELAYNE_BLOCKS_VERSIONconstant
Example workflow for version 2.2.3:
# CHANGELOG.md
## [2.2.3] - 2026-01-16
### Fixed
- Description of fix# readme.txt (line 7)
Stable tag: 2.2.3
# readme.txt (changelog section)
= 2.2.3 =
* Description of fix
// elayne-blocks.php (line 6)
* Version: 2.2.3
// elayne-blocks.php (line 26)
define( 'ELAYNE_BLOCKS_VERSION', '2.2.3' );All three files must be updated together to maintain version consistency across the plugin.