- Add WP Media Library integration for product and variation images - Support images array (URLs) conversion to attachment IDs - Add images array to API responses (Admin & Customer SPA) - Implement drag-and-drop sortable images in Admin product form - Add image gallery thumbnails in Customer SPA product page - Initialize WooCommerce session for guest cart operations - Fix product variations and attributes display in Customer SPA - Add variation image field in Admin SPA Changes: - includes/Api/ProductsController.php: Handle images array, add to responses - includes/Frontend/ShopController.php: Add images array for customer SPA - includes/Frontend/CartController.php: Initialize WC session for guests - admin-spa/src/lib/wp-media.ts: Add openWPMediaGallery function - admin-spa/src/routes/Products/partials/tabs/GeneralTab.tsx: WP Media + sortable images - admin-spa/src/routes/Products/partials/tabs/VariationsTab.tsx: Add variation image field - customer-spa/src/pages/Product/index.tsx: Add gallery thumbnails display
11 KiB
11 KiB
WooNooW Customer SPA Architecture
🎯 Core Decision: Full SPA Takeover (No Hybrid)
❌ What We're NOT Doing (Lessons Learned)
REJECTED: Hybrid SSR + SPA approach
- WordPress renders HTML (SSR)
- React hydrates on top (SPA)
- WooCommerce hooks inject content
- Theme controls layout
PROBLEMS EXPERIENCED:
- ✗ Script loading hell (spent 3+ hours debugging)
- ✗ React Refresh preamble errors
- ✗ Cache conflicts
- ✗ Theme conflicts
- ✗ Hook compatibility nightmare
- ✗ Inconsistent UX (some pages SSR, some SPA)
- ✗ Not truly "single-page" - full page reloads
✅ What We're Doing Instead
APPROVED: Full SPA Takeover
- React controls ENTIRE page (including
<html>,<body>) - Zero WordPress theme involvement
- Zero WooCommerce template rendering
- Pure client-side routing
- All data via REST API
BENEFITS:
- ✓ Clean separation of concerns
- ✓ True SPA performance
- ✓ No script loading issues
- ✓ No theme conflicts
- ✓ Predictable behavior
- ✓ Easy to debug
🏗️ Architecture Overview
System Diagram
┌─────────────────────────────────────────────────────┐
│ WooNooW Plugin │
├─────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ Admin SPA │ │ Customer SPA │ │
│ │ (React) │ │ (React) │ │
│ │ │ │ │ │
│ │ - Products │ │ - Shop │ │
│ │ - Orders │ │ - Product Detail │ │
│ │ - Customers │ │ - Cart │ │
│ │ - Analytics │ │ - Checkout │ │
│ │ - Settings │◄─────┤ - My Account │ │
│ │ └─ Customer │ │ │ │
│ │ SPA Config │ │ Uses settings │ │
│ └────────┬─────────┘ └────────┬─────────┘ │
│ │ │ │
│ └────────┬────────────────┘ │
│ │ │
│ ┌──────────▼──────────┐ │
│ │ REST API Layer │ │
│ │ (PHP Controllers) │ │
│ └──────────┬──────────┘ │
│ │ │
│ ┌──────────▼──────────┐ │
│ │ WordPress Core │ │
│ │ + WooCommerce │ │
│ │ (Data Layer Only) │ │
│ └─────────────────────┘ │
└─────────────────────────────────────────────────────┘
🔧 Three-Mode System
Mode 1: Admin Only (Default)
✅ Admin SPA: Active (product management, orders, etc.)
❌ Customer SPA: Inactive
→ User uses their own theme/page builder for frontend
Mode 2: Full SPA (Complete takeover)
✅ Admin SPA: Active
✅ Customer SPA: Full Mode (takes over entire site)
→ WooNooW controls everything
→ Choose from 4 layouts: Classic, Modern, Boutique, Launch
Mode 3: Checkout-Only SPA 🆕 (Hybrid approach)
✅ Admin SPA: Active
✅ Customer SPA: Checkout Mode (partial takeover)
→ Only overrides: Checkout → Thank You → My Account
→ User keeps theme/page builder for landing pages
→ Perfect for single product sellers with custom landing pages
Settings UI:
Admin SPA > Settings > Customer SPA
Customer SPA Mode:
○ Disabled (Use your own theme)
○ Full SPA (Take over entire storefront)
● Checkout Only (Override checkout pages only)
If Checkout Only selected:
Pages to override:
[✓] Checkout
[✓] Thank You (Order Received)
[✓] My Account
[ ] Cart (optional)
🔌 Technical Implementation
1. Customer SPA Activation Flow
// When user enables Customer SPA in Admin SPA:
1. Admin SPA sends: POST /wp-json/woonoow/v1/settings/customer-spa
{
"enabled": true,
"layout": "modern",
"colors": {...},
...
}
2. PHP saves to wp_options:
update_option('woonoow_customer_spa_enabled', true);
update_option('woonoow_customer_spa_settings', $settings);
3. PHP activates template override:
- template_include filter returns spa-full-page.php
- Dequeues all theme scripts/styles
- Outputs minimal HTML with React mount point
4. React SPA loads and takes over entire page
2. Template Override (PHP)
File: includes/Frontend/TemplateOverride.php
public static function use_spa_template($template) {
$mode = get_option('woonoow_customer_spa_mode', 'disabled');
// Mode 1: Disabled
if ($mode === 'disabled') {
return $template; // Use normal theme
}
// Mode 3: Checkout-Only (partial SPA)
if ($mode === 'checkout_only') {
$checkout_pages = get_option('woonoow_customer_spa_checkout_pages', [
'checkout' => true,
'thankyou' => true,
'account' => true,
'cart' => false,
]);
if (($checkout_pages['checkout'] && is_checkout()) ||
($checkout_pages['thankyou'] && is_order_received_page()) ||
($checkout_pages['account'] && is_account_page()) ||
($checkout_pages['cart'] && is_cart())) {
return plugin_dir_path(__DIR__) . '../templates/spa-full-page.php';
}
return $template; // Use theme for other pages
}
// Mode 2: Full SPA
if ($mode === 'full') {
// Override all WooCommerce pages
if (is_woocommerce() || is_cart() || is_checkout() || is_account_page()) {
return plugin_dir_path(__DIR__) . '../templates/spa-full-page.php';
}
}
return $template;
}
3. SPA Template (Minimal HTML)
File: templates/spa-full-page.php
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo('charset'); ?>">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?php wp_title('|', true, 'right'); ?><?php bloginfo('name'); ?></title>
<?php wp_head(); // Loads WooNooW scripts only ?>
</head>
<body <?php body_class('woonoow-spa'); ?>>
<!-- React mount point -->
<div id="woonoow-customer-app"></div>
<?php wp_footer(); ?>
</body>
</html>
That's it! No WordPress theme markup, no WooCommerce templates.
4. React SPA Entry Point
File: customer-spa/src/main.tsx
import React from 'react';
import { createRoot } from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import App from './App';
import './index.css';
// Get config from PHP
const config = window.woonoowCustomer;
// Mount React app
const root = document.getElementById('woonoow-customer-app');
if (root) {
createRoot(root).render(
<React.StrictMode>
<BrowserRouter>
<App config={config} />
</BrowserRouter>
</React.StrictMode>
);
}
5. React Router (Client-Side Only)
File: customer-spa/src/App.tsx
import { Routes, Route } from 'react-router-dom';
import { ThemeProvider } from './contexts/ThemeContext';
import Layout from './components/Layout';
import Shop from './pages/Shop';
import Product from './pages/Product';
import Cart from './pages/Cart';
import Checkout from './pages/Checkout';
import Account from './pages/Account';
export default function App({ config }) {
return (
<ThemeProvider config={config.theme}>
<Layout>
<Routes>
<Route path="/shop" element={<Shop />} />
<Route path="/product/:slug" element={<Product />} />
<Route path="/cart" element={<Cart />} />
<Route path="/checkout" element={<Checkout />} />
<Route path="/my-account/*" element={<Account />} />
</Routes>
</Layout>
</ThemeProvider>
);
}
Key Point: React Router handles ALL navigation. No page reloads!
📋 Implementation Roadmap
Phase 1: Core Infrastructure ✅ (DONE)
- Full-page SPA template
- Script loading (Vite dev server)
- React Refresh preamble fix
- Template override system
- Dequeue conflicting scripts
Phase 2: Settings System (NEXT)
- Create Settings REST API endpoint
- Build Settings UI in Admin SPA
- Implement color picker component
- Implement layout selector
- Save/load settings from wp_options
Phase 3: Theme System
- Create 3 master layouts (Classic, Modern, Boutique)
- Implement design token system
- Build ThemeProvider
- Apply theme to all components
Phase 4: Homepage Builder
- Create section components (Hero, Featured, etc.)
- Build drag-drop section manager
- Section configuration modals
- Dynamic section rendering
Phase 5: Navigation
- Fetch WP menus via REST API
- Render menus in SPA
- Mobile menu component
- Mega menu support
Phase 6: Pages
- Shop page (product grid)
- Product detail page
- Cart page
- Checkout page
- My Account pages
✅ Decision Log
| Decision | Rationale | Date |
|---|---|---|
| Full SPA takeover (no hybrid) | Hybrid SSR+SPA caused script loading hell, cache issues, theme conflicts | Nov 22, 2024 |
| Settings in Admin SPA (not wp-admin) | Consistent UX, better UI components, easier to maintain | Nov 22, 2024 |
| 3 master layouts (not infinite) | SaaS approach: curated options > infinite flexibility | Nov 22, 2024 |
| Design tokens (not custom CSS) | Maintainable, predictable, accessible | Nov 22, 2024 |
| Client-side routing only | True SPA performance, no page reloads | Nov 22, 2024 |
📚 Related Documentation
- Customer SPA Settings - Settings schema & API
- Customer SPA Theme System - Design tokens & layouts
- Customer SPA Development - Dev guide for contributors