]>(
'woonoow_order_form_after_shipping',
(content, formData, setFormData) => {
// TypeScript knows the types!
return ;
}
);
```
---
## Component Development
### Basic Component
```typescript
// dist/MyPage.tsx
import React from 'react';
export default function MyPage() {
return (
);
}
```
### Access WooNooW APIs
```typescript
// Access REST API
const api = (window as any).WNW_API;
const response = await fetch(`${api.root}my-addon/endpoint`, {
headers: { 'X-WP-Nonce': api.nonce },
});
// Access store data
const store = (window as any).WNW_STORE;
console.log('Currency:', store.currency);
// Access site info
const wnw = (window as any).wnw;
console.log('Site Title:', wnw.siteTitle);
```
### Use WooNooW Components
```typescript
import { __ } from '@/lib/i18n';
import { formatMoney } from '@/lib/currency';
import { Button } from '@/components/ui/button';
import { Card } from '@/components/ui/card';
export default function MyPage() {
return (
{__('My Addon', 'my-addon')}
{formatMoney(1234.56)}
);
}
```
### Build Configuration
```javascript
// vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
build: {
lib: {
entry: 'src/index.ts',
name: 'MyAddon',
fileName: 'addon',
formats: ['es'],
},
rollupOptions: {
external: ['react', 'react-dom'],
output: {
globals: {
react: 'React',
'react-dom': 'ReactDOM',
},
},
},
},
});
```
---
## Best Practices
### ✅ DO:
1. **Use Hook System for Functional Extensions**
```typescript
// ✅ Good - No hardcoding
addFilter('woonoow_order_form_after_shipping', ...);
```
2. **Use Route Injection for New Pages**
```php
// ✅ Good - Separate UI
add_filter('woonoow/spa_routes', ...);
```
3. **Declare Dependencies**
```php
'dependencies' => ['woocommerce' => '8.0']
```
4. **Check Capabilities**
```php
'capability' => 'manage_woocommerce'
```
5. **Internationalize Strings**
```php
'label' => __('My Addon', 'my-addon')
```
6. **Handle Errors Gracefully**
```typescript
try {
await api.post(...);
} catch (error) {
toast.error('Failed to save');
}
```
### ❌ DON'T:
1. **Don't Hardcode Addon Components in Core**
```typescript
// ❌ Bad - Breaks if addon not installed
import { SubdistrictSelector } from 'addon';
// ✅ Good - Use hooks
{applyFilters('woonoow_order_form_after_shipping', null)}
```
2. **Don't Skip Capability Checks**
```php
// ❌ Bad
'capability' => ''
// ✅ Good
'capability' => 'manage_woocommerce'
```
3. **Don't Modify Core Navigation**
```php
// ❌ Bad
unset($tree[0]);
// ✅ Good
$tree[] = ['key' => 'my-addon', ...];
```
---
## Examples
### Example 1: Simple UI Addon (Route Injection Only)
```php
'reports',
'name' => 'Reports',
'version' => '1.0.0',
];
return $addons;
});
add_filter('woonoow/spa_routes', function($routes) {
$routes[] = [
'path' => '/reports',
'component_url' => plugin_dir_url(__FILE__) . 'dist/Reports.js',
'title' => 'Reports',
];
return $routes;
});
add_filter('woonoow/nav_tree', function($tree) {
$tree[] = [
'key' => 'reports',
'label' => 'Reports',
'path' => '/reports',
'icon' => 'bar-chart',
];
return $tree;
});
```
### Example 2: Functional Addon (Hook System Only)
```typescript
// Indonesia Shipping - No UI pages, just extends OrderForm
import { addonLoader, addFilter } from '@woonoow/hooks';
import { SubdistrictSelector } from './components/SubdistrictSelector';
addonLoader.register({
id: 'indonesia-shipping',
name: 'Indonesia Shipping',
version: '1.0.0',
init: () => {
addFilter('woonoow_order_form_after_shipping', (content, formData, setFormData) => {
return (
<>
{content}
📍 Shipping Destination
setFormData({
...formData,
shipping: { ...formData.shipping, subdistrict_id: id }
})}
/>
>
);
});
}
});
```
### Example 3: Full-Featured Addon (Both Systems)
```php
'subscriptions',
'name' => 'Subscriptions',
'version' => '1.0.0',
'spa_bundle' => plugin_dir_url(__FILE__) . 'dist/addon.js',
];
return $addons;
});
add_filter('woonoow/spa_routes', function($routes) {
$routes[] = [
'path' => '/subscriptions',
'component_url' => plugin_dir_url(__FILE__) . 'dist/SubscriptionsList.js',
];
return $routes;
});
add_filter('woonoow/nav_tree', function($tree) {
$tree[] = [
'key' => 'subscriptions',
'label' => 'Subscriptions',
'path' => '/subscriptions',
'icon' => 'repeat',
];
return $tree;
});
```
```typescript
// Frontend: Hook integration
import { addonLoader, addFilter } from '@woonoow/hooks';
addonLoader.register({
id: 'subscriptions',
name: 'Subscriptions',
version: '1.0.0',
init: () => {
// Add subscription fields to order form
addFilter('woonoow_order_form_custom_sections', (content, formData, setFormData) => {
return (
<>
{content}
>
);
});
// Add subscription fields to product form
addFilter('woonoow_product_form_fields', (content, formData, setFormData) => {
return (
<>
{content}
>
);
});
}
});
```
---
## Troubleshooting
### Addon Not Appearing?
- Check dependencies are met
- Verify capability requirements
- Check browser console for errors
- Flush caches: `?flush_wnw_cache=1`
### Route Not Loading?
- Verify `component_url` is correct
- Check file exists and is accessible
- Look for JS errors in console
- Ensure component exports `default`
### Hook Not Firing?
- Check hook name is correct
- Verify addon is registered
- Check `window.WNW_ADDONS` in console
- Ensure `init()` function runs
### Component Not Rendering?
- Check for React errors in console
- Verify component returns valid JSX
- Check props are passed correctly
- Test component in isolation
---
## Support & Resources
**Documentation:**
- `ADDON_INJECTION_GUIDE.md` - SPA route injection (legacy)
- `ADDON_HOOK_SYSTEM.md` - Hook system details (legacy)
- `BITESHIP_ADDON_SPEC.md` - Indonesia shipping example
- `SHIPPING_ADDON_RESEARCH.md` - Shipping integration patterns
**Code References:**
- `includes/Compat/AddonRegistry.php` - Addon registration
- `includes/Compat/RouteRegistry.php` - Route management
- `includes/Compat/NavigationRegistry.php` - Navigation building
- `admin-spa/src/lib/hooks.ts` - Hook system implementation
- `admin-spa/src/App.tsx` - Dynamic route loading
---
**End of Guide**
**Version:** 2.0.0
**Last Updated:** November 9, 2025
**Status:** ✅ Production Ready
**This is the single source of truth for WooNooW addon development.**