---
title: Module Registry
description: Register custom modules and addons with WooNooW's unified module system
---

WooNooW's modular architecture allows developers to create custom modules and addons that integrate seamlessly with the **Settings > Modules** UI.

## Overview

The Module Registry provides a unified system for:
- Enable/disable toggle in the admin UI
- Custom settings with schema-based forms
- Dependencies on other modules
- SPA route registration for custom settings pages

## Registering a Module

Add your module using the `woonoow/modules/registry` filter:

```php
add_filter('woonoow/modules/registry', 'my_plugin_register_module');

function my_plugin_register_module($modules) {
    $modules['my-module'] = [
        'id'          => 'my-module',
        'name'        => __('My Custom Module', 'my-plugin'),
        'description' => __('Description of what this module does.', 'my-plugin'),
        'icon'        => 'Sparkles', // Lucide icon name
        'category'    => 'marketing', // marketing, sales, developer, etc.
        'requires'    => [], // Array of required module IDs
        'settings'    => [], // Settings schema array
    ];
    
    return $modules;
}
```

## Module Properties

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `id` | string | Yes | Unique identifier (lowercase, hyphens) |
| `name` | string | Yes | Display name in the UI |
| `description` | string | Yes | Brief description of functionality |
| `icon` | string | No | Lucide icon name (e.g., `Package`, `Mail`) |
| `category` | string | No | Grouping category: `marketing`, `sales`, `developer` |
| `requires` | array | No | Array of module IDs this depends on |
| `settings` | array | No | Settings schema for module configuration |

---

## Settings Schema

Define a settings schema to allow users to configure your module:

```php
'settings' => [
    [
        'id'          => 'api_key',
        'type'        => 'text',
        'label'       => __('API Key', 'my-plugin'),
        'description' => __('Enter your API key', 'my-plugin'),
        'default'     => '',
    ],
    [
        'id'          => 'rate_limit',
        'type'        => 'number',
        'label'       => __('Rate Limit', 'my-plugin'),
        'description' => __('Max requests per minute', 'my-plugin'),
        'default'     => 10,
        'min'         => 1,
        'max'         => 100,
    ],
    [
        'id'          => 'enable_debug',
        'type'        => 'toggle',
        'label'       => __('Enable Debug Mode', 'my-plugin'),
        'default'     => false,
    ],
],
```

### Available Field Types

| Type | Description | Properties |
|------|-------------|------------|
| `text` | Single-line text input | `default`, `placeholder` |
| `textarea` | Multi-line text input | `default`, `rows` |
| `number` | Numeric input with validation | `default`, `min`, `max`, `step` |
| `toggle` | Boolean on/off switch | `default` (true/false) |
| `select` | Dropdown selection | `default`, `options` (array of `{value, label}`) |
| `checkbox` | Single checkbox | `default` (true/false) |
| `color` | Color picker | `default` (#hex value) |
| `url` | URL input with validation | `default`, `placeholder` |
| `email` | Email input with validation | `default`, `placeholder` |
| `password` | Password input (masked) | `default` |

### Common Field Properties

| Property | Type | Description |
|----------|------|-------------|
| `id` | string | Unique field identifier |
| `type` | string | Field type from list above |
| `label` | string | Display label |
| `description` | string | Help text below field |
| `default` | mixed | Default value |

### Select Field Example

```php
[
    'id'      => 'display_mode',
    'type'    => 'select',
    'label'   => __('Display Mode', 'my-plugin'),
    'default' => 'grid',
    'options' => [
        ['value' => 'grid', 'label' => __('Grid', 'my-plugin')],
        ['value' => 'list', 'label' => __('List', 'my-plugin')],
        ['value' => 'carousel', 'label' => __('Carousel', 'my-plugin')],
    ],
],
```

---

## Checking Module Status

Use `ModuleRegistry::is_enabled()` to check if your module is active:

```php
use WooNooW\Core\ModuleRegistry;

if (ModuleRegistry::is_enabled('my-module')) {
    // Module is enabled, initialize features
    My_Module_Manager::init();
}
```

## Module Lifecycle Events

Hook into module enable/disable events:

```php
// When any module is enabled
add_action('woonoow/module/enabled', function($module_id) {
    if ($module_id === 'my-module') {
        // Create database tables, initialize settings, etc.
        My_Module_Manager::install();
    }
});

// When any module is disabled
add_action('woonoow/module/disabled', function($module_id) {
    if ($module_id === 'my-module') {
        // Cleanup if necessary
    }
});
```

---

## SPA Routes for Settings Pages

Addons can register custom React settings pages:

```php
add_filter('woonoow/spa_routes', function($routes) {
    $routes[] = [
        'path'          => '/settings/my-addon',
        'component_url' => plugin_dir_url(__FILE__) . 'dist/Settings.js',
        'title'         => 'My Addon Settings',
    ];
    return $routes;
});
```

## Addon Registry (External Addons)

External addons can also register via `woonoow/addon_registry` for extended metadata:

```php
add_filter('woonoow/addon_registry', function($addons) {
    $addons['my-shipping-addon'] = [
        'id'           => 'my-shipping-addon',
        'name'         => 'My Shipping',
        'description'  => 'Custom shipping integration',
        'version'      => '1.0.0',
        'author'       => 'My Company',
        'category'     => 'shipping',
        'icon'         => 'truck',
        'settings_url' => '/settings/shipping/my-addon',
        'spa_bundle'   => plugin_dir_url(__FILE__) . 'dist/addon.js',
    ];
    return $addons;
});
```

---

## Complete Example

```php
<?php
namespace MyPlugin;

class MyModuleSettings {
    
    public static function init() {
        add_filter('woonoow/modules/registry', [__CLASS__, 'register']);
    }
    
    public static function register($modules) {
        $modules['my-module'] = [
            'id'          => 'my-module',
            'name'        => __('My Module', 'my-plugin'),
            'description' => __('Adds awesome features to your store.', 'my-plugin'),
            'icon'        => 'Zap',
            'category'    => 'marketing',
            'requires'    => [], // No dependencies
            'settings'    => [
                [
                    'id'      => 'feature_enabled',
                    'type'    => 'toggle',
                    'label'   => __('Enable Feature', 'my-plugin'),
                    'default' => true,
                ],
            ],
        ];
        
        return $modules;
    }
}

// Initialize on plugins_loaded
add_action('plugins_loaded', ['MyPlugin\MyModuleSettings', 'init']);
```

## Best Practices

1. **Check module status** before loading heavy features
2. **Use the `woonoow/module/enabled` hook** to run installation routines only when needed
3. **Specify dependencies** so WooNooW can prompt users to enable required modules
4. **Provide meaningful descriptions** to help users understand what each module does
