# WooNooW Addon Injection Guide **Version:** 1.0.0 **Last Updated:** 2025-10-28 **Status:** Production Ready --- ## 📋 Table of Contents 1. [Overview](#overview) 2. [Admin SPA Addons](#admin-spa-addons) - [Quick Start](#quick-start) - [Addon Registration](#addon-registration) - [Route Registration](#route-registration) - [Navigation Injection](#navigation-injection) - [Component Development](#component-development) - [Best Practices](#best-practices) 3. [Customer SPA Addons](#customer-spa-addons) *(Coming Soon)* 4. [Testing & Debugging](#testing--debugging) 5. [Examples](#examples) 6. [Troubleshooting](#troubleshooting) --- ## Overview WooNooW provides a **powerful addon injection system** that allows third-party plugins to seamlessly integrate with the React-powered admin SPA. Addons can: - ✅ Register custom SPA routes - ✅ Inject navigation menu items - ✅ Add submenu items to existing sections - ✅ Load React components dynamically - ✅ Declare dependencies and capabilities - ✅ Maintain full isolation and safety **No iframes, no hacks, just clean React integration!** --- ## Admin SPA Addons ### Quick Start **5-Minute Integration:** ```php 'my-addon', 'name' => 'My Addon', 'version' => '1.0.0', 'author' => 'Your Name', 'description' => 'My awesome addon', 'spa_bundle' => plugin_dir_url(__FILE__) . 'dist/addon.js', 'dependencies' => ['woocommerce' => '8.0'], ]; return $addons; }); // 2. Register your routes add_filter('woonoow/spa_routes', function($routes) { $routes[] = [ 'path' => '/my-addon', 'component_url' => plugin_dir_url(__FILE__) . 'dist/MyAddonPage.js', 'capability' => 'manage_woocommerce', 'title' => 'My Addon', ]; return $routes; }); // 3. Add navigation item add_filter('woonoow/nav_tree', function($tree) { $tree[] = [ 'key' => 'my-addon', 'label' => 'My Addon', 'path' => '/my-addon', 'icon' => 'puzzle', // lucide icon name 'children' => [], ]; return $tree; }); ``` **That's it!** Your addon is now integrated into WooNooW. --- ### Addon Registration **Filter:** `woonoow/addon_registry` **Priority:** 20 (runs on `plugins_loaded`) **File:** `includes/Compat/AddonRegistry.php` #### Configuration Schema ```php add_filter('woonoow/addon_registry', function($addons) { $addons['addon-id'] = [ // Required 'id' => 'addon-id', // Unique identifier 'name' => 'Addon Name', // Display name 'version' => '1.0.0', // Semantic version // Optional 'author' => 'Author Name', // Author name 'description' => 'Description', // Short description 'spa_bundle' => 'https://...', // Main JS bundle URL // Dependencies (optional) 'dependencies' => [ 'woocommerce' => '8.0', // Min WooCommerce version 'wordpress' => '6.0', // Min WordPress version ], // Advanced (optional) 'routes' => [], // Route definitions 'nav_items' => [], // Nav item definitions 'widgets' => [], // Widget definitions ]; return $addons; }); ``` #### Dependency Validation WooNooW automatically validates dependencies: ```php 'dependencies' => [ 'woocommerce' => '8.0', // Requires WooCommerce 8.0+ 'wordpress' => '6.4', // Requires WordPress 6.4+ ] ``` If dependencies are not met: - ❌ Addon is disabled automatically - ❌ Routes are not registered - ❌ Navigation items are hidden --- ### Route Registration **Filter:** `woonoow/spa_routes` **Priority:** 25 (runs on `plugins_loaded`) **File:** `includes/Compat/RouteRegistry.php` #### Basic Route ```php add_filter('woonoow/spa_routes', function($routes) { $routes[] = [ 'path' => '/subscriptions', 'component_url' => plugin_dir_url(__FILE__) . 'dist/SubscriptionsList.js', 'capability' => 'manage_woocommerce', 'title' => 'Subscriptions', ]; return $routes; }); ``` #### Multiple Routes ```php add_filter('woonoow/spa_routes', function($routes) { $base_url = plugin_dir_url(__FILE__) . 'dist/'; $routes[] = [ 'path' => '/subscriptions', 'component_url' => $base_url . 'SubscriptionsList.js', 'capability' => 'manage_woocommerce', 'title' => 'All Subscriptions', ]; $routes[] = [ 'path' => '/subscriptions/new', 'component_url' => $base_url . 'SubscriptionNew.js', 'capability' => 'manage_woocommerce', 'title' => 'New Subscription', ]; $routes[] = [ 'path' => '/subscriptions/:id', 'component_url' => $base_url . 'SubscriptionDetail.js', 'capability' => 'manage_woocommerce', 'title' => 'Subscription Detail', ]; return $routes; }); ``` #### Route Configuration | Property | Type | Required | Description | |----------|------|----------|-------------| | `path` | string | ✅ Yes | Route path (must start with `/`) | | `component_url` | string | ✅ Yes | URL to React component JS file | | `capability` | string | No | WordPress capability (default: `manage_woocommerce`) | | `title` | string | No | Page title | | `exact` | boolean | No | Exact path match (default: `false`) | | `props` | object | No | Props to pass to component | --- ### Navigation Injection #### Add Main Menu Item **Filter:** `woonoow/nav_tree` **Priority:** 30 (runs on `plugins_loaded`) **File:** `includes/Compat/NavigationRegistry.php` ```php add_filter('woonoow/nav_tree', function($tree) { $tree[] = [ 'key' => 'subscriptions', 'label' => __('Subscriptions', 'my-addon'), 'path' => '/subscriptions', 'icon' => 'repeat', // lucide-react icon name 'children' => [ [ 'label' => __('All Subscriptions', 'my-addon'), 'mode' => 'spa', 'path' => '/subscriptions', ], [ 'label' => __('New', 'my-addon'), 'mode' => 'spa', 'path' => '/subscriptions/new', ], ], ]; return $tree; }); ``` #### Inject into Existing Section **Filter:** `woonoow/nav_tree/{key}/children` ```php // Add "Bundles" to Products menu add_filter('woonoow/nav_tree/products/children', function($children) { $children[] = [ 'label' => __('Bundles', 'my-addon'), 'mode' => 'spa', 'path' => '/products/bundles', ]; return $children; }); // Add "Reports" to Dashboard menu add_filter('woonoow/nav_tree/dashboard/children', function($children) { $children[] = [ 'label' => __('Custom Reports', 'my-addon'), 'mode' => 'spa', 'path' => '/reports', ]; return $children; }); ``` #### Available Sections | Key | Label | Path | |-----|-------|------| | `dashboard` | Dashboard | `/` | | `orders` | Orders | `/orders` | | `products` | Products | `/products` | | `coupons` | Coupons | `/coupons` | | `customers` | Customers | `/customers` | | `settings` | Settings | `/settings` | #### Navigation Item Schema ```typescript { key: string; // Unique key (for main items) label: string; // Display label (i18n recommended) path: string; // Route path icon?: string; // Lucide icon name (main items only) mode: 'spa' | 'bridge'; // Render mode href?: string; // External URL (bridge mode) exact?: boolean; // Exact path match children?: SubItem[]; // Submenu items } ``` #### Lucide Icons WooNooW uses [lucide-react](https://lucide.dev/) icons (16-20px, 1.5px stroke). **Popular icons:** - `layout-dashboard` - Dashboard - `receipt-text` - Orders - `package` - Products - `tag` - Coupons - `users` - Customers - `settings` - Settings - `repeat` - Subscriptions - `calendar` - Bookings - `credit-card` - Payments - `bar-chart` - Analytics --- ### Component Development #### Component Structure Your React component will be dynamically imported and rendered: ```typescript // dist/MyAddonPage.tsx import React from 'react'; export default function MyAddonPage(props: any) { return (
Welcome to my addon!
{formatMoney(1234.56)}