Backend improvements: - Add cache auto-clear on settings save (class-settings-v2.php) - Hooks updated_option action - Clears connection test transients when local backend settings change - Add reasoning_content streaming support (class-local-backend-provider.php) - Handles thinking models like Claude extended thinking - Captures chunk['choices'][0]['delta']['reasoning_content'] Documentation: - Add FRONTEND_AND_CHAT_FIX_SUMMARY.md with all fixes - Add FRONTEND-REFACTOR-PHASE2.md with modularization plan Note: Splitting effort deferred - will continue iterating on monolith Next: Fix session history not appearing bug
8.4 KiB
Frontend Refactor Phase 2: Modularization Plan
Date: 2026-06-17
Status: 📋 IN PROGRESS
Author: Agent
Reference: FRONTEND_AND_CHAT_FIX_SUMMARY.md
Session Summary (2026-06-17)
Completed Backend Improvements
| Task | File | Status |
|---|---|---|
| Connection test caching | class-provider-manager.php |
✅ Already existed |
| Cache auto-clear on settings save | class-settings-v2.php |
✅ Added |
| Reasoning content parsing | class-local-backend-provider.php |
✅ Added |
Files Modified This Session
-
includes/class-settings-v2.php- Added
clear_local_backend_cache_on_settings_change()method - Hooked to
updated_optionaction - Clears connection test transients when local backend settings change
- Added
-
includes/class-local-backend-provider.php- Added
reasoning_contentstreaming support (lines ~494-520) - Handles thinking models like Claude extended thinking
- Debug logging included
- Added
Validation Results
| Check | Result |
|---|---|
npm run build |
✅ Passes |
| PHP syntax (all modified files) | ✅ Passes |
| Build output | dist/sidebar.js (169 KB) |
Overview
This document outlines the approach for splitting the monolithic assets/js/src/index.jsx (11,793 lines) into modular React components, hooks, and utilities while maintaining the existing build pipeline.
Key Principle
The build pipeline (
scripts/build.js→assets/js/dist/sidebar.js) already works correctly. We are refactoring the source for maintainability, NOT fixing a broken build.
Important: Two sidebar.js Files
| File | Source of Truth? | Loaded by PHP? |
|---|---|---|
assets/js/sidebar.js |
❌ Legacy (webpack, 438KB) | ❌ No |
assets/js/dist/sidebar.js |
✅ Current (esbuild, 169KB) | ✅ Yes |
Do NOT confuse the two files. The legacy
sidebar.js(438KB) is the original monolithic file that was never modularized. Thedist/sidebar.js(169KB) is the esbuild-compiled output fromsrc/index.jsx.
Current State
Build Pipeline (Working ✅)
assets/js/src/index.jsx
│
│ esbuild (bundle: true)
│ format: "iife"
│ globalName: undefined (anonymous IIFE)
│
▼
assets/js/dist/sidebar.js (compiled, served to WordPress) ✅
Source & Output Files
| Path | Lines/Size | Purpose | Status |
|---|---|---|---|
src/index.jsx |
11,793 | React source (to be split) | ✅ Active |
dist/sidebar.js |
169 KB | Compiled output (loaded by PHP) | ✅ Active |
sidebar.js |
438 KB | Legacy file (NOT loaded) | ⚠️ Archived |
Build Validation (2026-06-17) ✅
| Check | Result |
|---|---|
npm run build |
✅ Passes (165.8kb output) |
| PHP syntax (settings) | ✅ Passes |
| PHP syntax (provider) | ✅ Passes |
| PHP syntax (provider manager) | ✅ Passes |
| PHP syntax (local backend) | ✅ Passes |
PHP loads dist/sidebar.js |
✅ Confirmed in class-gutenberg-sidebar.php:217 |
esbuild Configuration
The scripts/build.js uses bundle: true, which means:
- All local imports are resolved automatically
- No need for separate bundler config
- Extracted files will compile seamlessly
Proposed Directory Structure
assets/js/
├── src/
│ ├── index.jsx # Main entry, imports all modules
│ ├── components/
│ │ ├── ChatTab.jsx # Chat tab content
│ │ ├── ConfigTab.jsx # Configuration tab
│ │ ├── CostTab.jsx # Cost tracking tab
│ │ ├── WelcomeScreen.jsx # Welcome/home screen
│ │ ├── Clarification.jsx # Clarification quiz UI
│ │ ├── AgentWorkspaceCard.jsx
│ │ ├── ContextualAction.jsx
│ │ ├── FocusKeywordBar.jsx
│ │ ├── Messages.jsx # Message rendering
│ │ ├── GlobalStatusBar.jsx
│ │ └── RefineAllModal.jsx
│ ├── hooks/
│ │ ├── useChatHistory.js
│ │ ├── useSessionLock.js
│ │ ├── usePostConfig.js
│ │ ├── useWritingState.js
│ │ └── useStreaming.js
│ ├── utils/
│ │ ├── api.js # REST API helpers
│ │ ├── blockUtils.js # Block manipulation
│ │ ├── planUtils.js # Plan parsing/building
│ │ ├── streamUtils.js # Streaming utilities
│ │ ├── markdownUtils.js # Markdown rendering
│ │ └── formatUtils.js # Formatting helpers
│ └── styles/
│ └── components.css # Component-specific styles
└── dist/
└── sidebar.js # Compiled output (auto-generated)
Extraction Strategy
Phase 1: Extract Utilities (Low Risk)
Begin with pure functions that have no React dependencies:
-
formatAiErrorMessage(lines 42-136)- Pure function, no side effects
- Easy to extract and test
-
markdownToHtml/inlineMarkdownToHtml(lines 10015-10270)- Large but isolated
- No state dependencies
-
Block utility functions
createBlocksFromSerializedgetBlockContentForContextgetHeadingContextForBlock
Phase 2: Extract Custom Hooks
-
useChatHistory- Session loading, saving, message persistence
- Isolated state management
-
useSessionLock- Tab locking mechanism
- Heartbeat management
-
useStreaming- SSE parsing
- Chunk accumulation
- Error handling
Phase 3: Extract UI Components
-
Tabs (Chat, Config, Cost)
- Each tab can be its own component
- Share state via props or context
-
WelcomeScreen
- Self-contained, minimal dependencies
-
Clarification Quiz
- Complex but isolated UI
Phase 4: Extract Editor Integration
The most complex part - interactions with WordPress block editor:
- Block mutation observation
- Input blocking
- Undo/redo integration
Migration Pattern
Before (in index.jsx)
const AgenticWriterSidebar = ({ postId }) => {
const formatAiErrorMessage = (error) => { /* ... */ };
const sendMessage = async (msg) => { /* ... */ };
return <div>...</div>;
};
After (modular)
src/utils/formatUtils.js
export const formatAiErrorMessage = (error, fallback, settings) => {
// ...
};
src/hooks/useChatApi.js
export const useChatApi = () => {
const sendMessage = async (msg) => { /* ... */ };
return { sendMessage };
};
src/index.jsx
import { formatAiErrorMessage } from './utils/formatUtils';
import { useChatApi } from './hooks/useChatApi';
import { ChatTab } from './components/ChatTab';
const AgenticWriterSidebar = ({ postId }) => {
const { sendMessage } = useChatApi();
return <ChatTab onSend={sendMessage} />;
};
Verification Checklist
After each extraction:
npm run buildcompletes without errors- Compiled
sidebar.jsmatches expected size (±5%) - Chat functionality works (send message, receive response)
- Planning functionality works (generate plan)
- Refinement works (refine blocks)
- Tab switching works
- Session persistence works
- No console errors in browser
Rollback Plan
If extraction causes issues:
- Revert the specific extracted file
- Keep extracted utilities (safe to keep)
- Re-run
npm run build - Verify functionality
Next Action
- Create
src/utils/directory - Extract
formatAiErrorMessageas the first migration - Verify build and functionality
- Iterate with next extraction
Dependencies
| Tool | Status |
|---|---|
| esbuild | ✅ Configured |
| npm | ✅ Available |
| WordPress environment | ✅ Local by Flywheel |
Questions to Resolve Before Starting
- Should extracted components use TypeScript or remain JSX?
- Should we add PropTypes for component prop validation?
- Should we maintain backward compatibility with
wpAgenticWriterglobal?
References
FRONTEND_AND_CHAT_FIX_SUMMARY.md- Original fix documentationscripts/build.js- Current esbuild configurationassets/js/dist/sidebar.js- Compiled output (loaded by PHP, 169KB)assets/js/sidebar.js- Legacy file (archived, 438KB, NOT loaded)assets/js/src/index.jsx- Current source (to be split, 11,793 lines)