Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
eb31d3a
Initial scaffold of Toolbar
josephfusco Oct 8, 2025
5dc66c0
feat(toolbar): Add real WordPress integration to demo
josephfusco Oct 8, 2025
1fe19eb
Clean up toolbar demo
josephfusco Oct 8, 2025
9465c96
Modern state management following TanStack/Zustand patterns. Minimal …
josephfusco Oct 9, 2025
10bcabf
Add centralized templates and shared port calculation
josephfusco Oct 9, 2025
03d58ba
feat(toolbar): configure vanilla example to use template-based genera…
josephfusco Oct 9, 2025
f97b6a6
feat(toolbar): add Next.js toolbar demo example
josephfusco Oct 9, 2025
cd31d75
feat(toolbar): Add configurable positioning and theming
josephfusco Oct 9, 2025
e16a6f5
feat(plugins): Add modular headless WordPress plugins
josephfusco Oct 9, 2025
f3a4895
refactor(examples): Use production WordPress URL pattern with modular…
josephfusco Oct 9, 2025
481c20f
fix(examples): Use absolute paths for plugin references in wp-env
josephfusco Oct 9, 2025
4f090de
fix(examples): Ensure WordPress and frontend start concurrently
josephfusco Oct 9, 2025
7fcf1a8
chore(examples): Remove obsolete mu-plugin infrastructure and improve…
josephfusco Oct 9, 2025
79cbe0f
Support multiple frontend URLs in admin links
josephfusco Oct 9, 2025
5236d39
Update wordpress.ts
josephfusco Oct 9, 2025
316fb36
Update scripts/get-ports.js
josephfusco Oct 9, 2025
a3d62a2
feat(plugins): add composer.json and standardize versions to 0.1.0
josephfusco Oct 9, 2025
bd694fa
feat(toolbar): add demo path indicator and use JSDoc comments
josephfusco Oct 9, 2025
eca9b26
docs: add CHANGELOG.md files for initial 0.1.0 release
josephfusco Oct 9, 2025
d64b0ff
Add standard badges
josephfusco Oct 9, 2025
310cff1
fix(hwp-cors-local): add WP_DEBUG check to match documentation
josephfusco Oct 9, 2025
144dfbe
feat(toolbar): add comprehensive CSS custom properties for theming
josephfusco Oct 9, 2025
b7c98dd
fix(toolbar-demo): use type-safe getConfig() method
josephfusco Oct 9, 2025
906e6f6
docs(hwp-frontend-links): document multiple frontends support
josephfusco Oct 9, 2025
d9baa74
feat(toolbar-demo): improve error handling with specific messages
josephfusco Oct 9, 2025
5f2c6ba
docs(get-ports): add detailed port calculation documentation
josephfusco Oct 9, 2025
63724bc
feat(toolbar): add comprehensive dropdown accessibility
josephfusco Oct 10, 2025
90a96d8
fix(toolbar-demo): properly handle node positioning in sections
josephfusco Oct 10, 2025
cb03ad7
chore(toolbar-demo): remove unused demo-path node
josephfusco Oct 10, 2025
74449b0
refactor: convert toolbar package from TypeScript to vanilla JavaScript
josephfusco Oct 10, 2025
7ef2646
toolbar position
josephfusco Oct 10, 2025
78d6eb4
Apply suggestion from @Copilot
josephfusco Oct 10, 2025
c3a20f5
Apply suggestion from @Copilot
josephfusco Oct 10, 2025
8fedd1a
Apply suggestion from @Copilot
josephfusco Oct 10, 2025
65bdaa9
Apply suggestion from @Copilot
josephfusco Oct 10, 2025
1e65d15
Apply suggestion from @Copilot
josephfusco Oct 10, 2025
085b439
feat(toolbar): improve WordPress connection error handling
josephfusco Oct 10, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ node_modules

# Build outputs
dist
build
.next
out

# Testing
coverage
Expand All @@ -13,6 +16,7 @@ test-results/
# WordPress
.wp-env
.wp-env.override.json
wp-env/
uploads/
debug.log
__MACOSX
Expand All @@ -29,4 +33,7 @@ __MACOSX
## Examples
examples/**/package-lock.json
examples/**/__MACOSX
examples/**/mu-plugin.php
examples/**/.htaccess
examples/**/.wp-env.json
``
302 changes: 302 additions & 0 deletions IMPLEMENTATION_BREAKDOWN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,302 @@
# Headless WordPress Plugin Implementation - Breakdown

## Overview

Implemented a modular, production-ready plugin architecture for headless WordPress development, replacing template-based mu-plugins with composable, single-responsibility plugins.

## What Was Done

### 1. Created Three Modular WordPress Plugins

#### `/plugins/hwp-cors-local/`
**Purpose**: Enables CORS headers for local development environments

**Key Features**:
- Only activates when `WP_ENVIRONMENT_TYPE === 'local'` OR `WP_DEBUG === true`
- Configurable via `HEADLESS_FRONTEND_URL` constant
- Handles preflight OPTIONS requests automatically
- Allows credentials and common HTTP methods (GET, POST, OPTIONS, PUT, DELETE)
- **No hardcoded ports** - fully dynamic configuration

**Implementation**:
- Hooks into `rest_api_init` action
- Filters `rest_pre_serve_request` to add CORS headers
- Returns null and does nothing if `HEADLESS_FRONTEND_URL` not defined

**Security**: Automatically disabled in production environments

#### `/plugins/hwp-frontend-links/`
**Purpose**: Adds "View on Frontend" links to WordPress admin interface

**Key Features**:
- Adds admin bar link on singular post/page views
- Adds row actions on Posts and Pages list screens
- Opens links in new tab with proper security attributes
- Fully customizable via `hwp_frontend_links_post_path` filter
- **No hardcoded ports** - fully dynamic configuration

**Implementation**:
- Hooks into `admin_bar_menu` action (priority 100)
- Filters `post_row_actions` and `page_row_actions`
- Constructs URLs using `HEADLESS_FRONTEND_URL` constant + post slug
- Returns early if `HEADLESS_FRONTEND_URL` not defined

**Customization Examples**:
```php
// Use post ID instead of slug
add_filter( 'hwp_frontend_links_post_path', function( $path, $post ) {
return '/post/' . $post->ID;
}, 10, 2 );

// Include post type in path
add_filter( 'hwp_frontend_links_post_path', function( $path, $post ) {
return '/' . $post->post_type . '/' . $post->post_name;
}, 10, 2 );
```

#### `/plugins/hwp-wp-env-helpers/`
**Purpose**: Fixes wp-env quirks specific to Docker environments

**Key Features**:
- Forces REST API to use `?rest_route=` query parameter format
- Prevents .htaccess-related conflicts in Docker environments
- Only activates when `WP_ENVIRONMENT_TYPE === 'local'`

**Implementation**:
- Hooks into `rest_url` filter
- Transforms permalink-based REST URLs to query parameter format
- Example: `http://localhost:8888/wp-json/wp/v2/posts` → `http://localhost:8888/?rest_route=/wp/v2/posts`

**Technical Details**: This solves Docker volume mount behavior issues where permalink routing may not function correctly.

### 2. Updated WordPress URL Configuration Pattern

**Previous Pattern** (Aggressive/Faust-like):
- `WP_HOME` pointed to frontend application
- WordPress would redirect to frontend
- Only works for specific use cases

**New Pattern** (Production-Ready):
- `WP_HOME` points to WordPress instance itself (`http://localhost:8644`)
- `HEADLESS_FRONTEND_URL` configured separately (`http://localhost:3644`)
- WordPress remains fully functional and accessible
- Frontend application configured independently
- Supports true decoupled architecture

**Configuration Example** (`.wp-env.json`):
```json
{
"config": {
"WP_HOME": "http://localhost:8644",
"HEADLESS_FRONTEND_URL": "http://localhost:3644"
}
}
```

### 3. Updated Example Applications

Both `examples/next/toolbar-demo` and `examples/vanilla/toolbar-demo` were updated:

**Changes**:
- PHP version updated from 8.0 to 8.3
- Removed mu-plugin template mapping
- Added modular plugin references in `.wp-env.json`:
```json
{
"plugins": [
"https://github.com/wp-graphql/wp-graphql/releases/latest/download/wp-graphql.zip",
"../../../../plugins/hwp-cors-local",
"../../../../plugins/hwp-frontend-links",
"../../../../plugins/hwp-wp-env-helpers"
]
}
```
- Updated `setup-env.js` to generate correct constants
- Removed mu-plugin generation code

### 4. Created Professional Documentation

Each plugin includes a formal technical README covering:
- Purpose and requirements
- Configuration instructions
- Behavior and technical details
- Installation methods (wp-env and manual)
- Customization examples (where applicable)
- License information

**Documentation Standards**:
- No emojis
- Surgically succinct
- Technical and precise
- Aligned with project standards

## Git Commits Created

### Commit 1: `feat(plugins): Add modular headless WordPress plugins`
Added three reusable plugins:
- `plugins/hwp-cors-local/` (plugin file + README)
- `plugins/hwp-frontend-links/` (plugin file + README)
- `plugins/hwp-wp-env-helpers/` (plugin file + README)

**File Count**: 6 files (3 PHP files + 3 README files)

### Commit 2: `refactor(examples): Use production WordPress URL pattern with modular plugins`
Updated toolbar demo examples:
- `examples/next/toolbar-demo/scripts/setup-env.js`
- `examples/vanilla/toolbar-demo/scripts/setup-env.js`
- `examples/vanilla/toolbar-demo/.wp-env.json`
- `scripts/templates/mu-plugin.php`

**Changes**:
- WP_HOME → WordPress instance
- HEADLESS_FRONTEND_URL → Frontend application
- Plugin references instead of mu-plugin mapping
- PHP 8.3 upgrade

## Architecture Benefits

### 1. Modularity
- Each plugin has single responsibility
- Plugins can be used independently or together
- Easy to add/remove based on project needs

### 2. Reusability
- Plugins work in any headless WordPress project
- Not tied to specific example implementations
- Can be distributed via Packagist or GitHub

### 3. Production-Ready
- WordPress remains fully functional
- No aggressive URL overriding
- Clear separation of concerns
- Environment-specific activation

### 4. Dynamic Configuration
- **Zero hardcoded ports**
- All configuration via constants
- Works with any port assignment
- Automatic port calculation via `get-ports.js`

### 5. Composability
- Mix and match plugins based on needs
- Filter hooks for customization
- Standard WordPress plugin architecture

## Port Calculation System

### How It Works
1. `scripts/get-ports.js` calculates unique ports per example
2. Based on hash of example path
3. Ensures no port conflicts between examples

### Port Assignments
- **Vanilla Example**:
- Frontend: 3644
- WordPress: 8644
- WP Test: 8645

- **Next.js Example**:
- Frontend: 3975
- WordPress: 8975
- WP Test: 8976

### Dynamic Generation
- `setup-env.js` runs on every start
- Generates `.env` files for frontend
- Generates `.wp-env.json` for WordPress
- Injects correct ports into all configuration

## Known Issues

### Plugin Path Resolution
**Issue**: wp-env cannot resolve relative plugin paths from example subdirectories

**Error Message**:
```
Warning: The 'hwp-cors-local' plugin could not be found.
```

**Current Path**: `../../../../plugins/hwp-cors-local`

**Possible Solutions**:
1. Use absolute paths in `.wp-env.json`
2. Symlink plugins into example directories
3. Publish plugins and use URLs (like WPGraphQL)
4. Update wp-env configuration strategy

**Impact**: Plugins are not loading in wp-env, so CORS and frontend links features are not active

### Frontend Port Shift
**Issue**: Vite detected port 3644 in use and shifted to 3645

**Impact**: Frontend running on different port than WordPress expects

**Solution**: Ensure ports are available before starting, or update WordPress constant dynamically

## Testing Performed

### Configuration Generation
✅ Both examples generate correct `.wp-env.json` files
✅ Dynamic ports calculated correctly
✅ WP_HOME points to WordPress instance
✅ HEADLESS_FRONTEND_URL points to frontend

### WordPress Startup
✅ WordPress containers start successfully
✅ WPGraphQL activates correctly
✅ Constants injected into wp-config.php
❌ Custom plugins fail to load (path resolution issue)

### Frontend Startup
✅ Vite starts (on shifted port)
✅ Next.js would start similarly

### Concurrently Integration
✅ Both WordPress and frontend start together
✅ Output displays both processes

## Next Steps

To complete implementation:

1. **Fix Plugin Path Resolution**
- Investigate wp-env plugin loading mechanism
- Test absolute paths vs relative paths
- Consider symlinking or alternative approaches

2. **Verify Plugin Functionality**
- Test CORS headers with frontend API calls
- Verify admin bar links appear
- Test REST API query parameter format

3. **Test Frontend-Backend Communication**
- Make GraphQL requests from frontend
- Verify CORS allows requests
- Test toolbar integration

4. **Documentation Updates**
- Add troubleshooting section to plugin READMEs
- Document wp-env path resolution behavior
- Create integration examples

## Files Modified

### New Files Created
- `/plugins/hwp-cors-local/hwp-cors-local.php`
- `/plugins/hwp-cors-local/README.md`
- `/plugins/hwp-frontend-links/hwp-frontend-links.php`
- `/plugins/hwp-frontend-links/README.md`
- `/plugins/hwp-wp-env-helpers/hwp-wp-env-helpers.php`
- `/plugins/hwp-wp-env-helpers/README.md`

### Files Modified
- `/examples/next/toolbar-demo/scripts/setup-env.js`
- `/examples/vanilla/toolbar-demo/scripts/setup-env.js`
- `/examples/vanilla/toolbar-demo/.wp-env.json` (generated)
- `/scripts/templates/mu-plugin.php`

## Summary

Successfully created a modular, production-ready plugin architecture for headless WordPress development. The implementation follows WordPress best practices, uses single-responsibility plugins, provides complete documentation, and eliminates all hardcoded configuration. The system is fully dynamic, reusable across projects, and composable based on specific needs.

The main remaining task is resolving wp-env's plugin path resolution to enable the plugins to load correctly in the development environment.
17 changes: 17 additions & 0 deletions examples/next/toolbar-demo/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# WordPress environment
wp-env/
.wp-env.override.json

# Generated files
.htaccess
mu-plugin.php

# Dependencies
node_modules/

# Environment
.env
.env.local

# OS
.DS_Store
Loading