WordPress Integration
Integrate MIDDAG React UI into a WordPress admin plugin using Inertia.js and the host adapter system.
Prerequisites
- WordPress 6.x+ with admin access
- PHP 8.2+ with Composer autoloading
- Inertia.js WordPress adapter — community package or custom integration
- Node.js 20+ and npm for the frontend build
Install
Navigate to your plugin's UI directory and install the package:
cd /path/to/wp-content/plugins/your-plugin/ui
npm install @middag-io/reactVite Config
Configure Vite to output a manifest for WordPress asset enqueuing:
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
build: {
outDir: '../assets/dist',
manifest: true,
},
});Asset enqueuing
Use the Vite manifest (manifest.json) to resolve hashed filenames when calling wp_enqueue_script() and wp_enqueue_style() in PHP.
Entry Point
Create your app entry point. WordPress plugins typically build as IIFE (single JS file) via wp_enqueue_script(). Use selective registration instead of registerDefaults() to avoid bundling heavy dependencies.
// main.tsx
import '@middag-io/react/style.css';
import './theme.css'; // ACCOUNT-specific token overrides
import {
ContractPage, I18nProvider,
registerShell, registerLayout, registerBlock,
ProductShell, StackLayout, SidebarLayout, DashboardLayout,
DenseTableBlock, MetricCardBlock, EmptyStateBlock,
FormPanelBlock, DetailPanelBlock, ActivityTimelineBlock,
TabbedPanelBlock, WorkflowProgressBlock,
} from '@middag-io/react';
// Selective registration -- only blocks this plugin uses
registerShell('product', ProductShell);
registerLayout('stack', StackLayout);
registerLayout('sidebar', SidebarLayout);
registerLayout('dashboard', DashboardLayout);
registerBlock('dense_table', DenseTableBlock);
registerBlock('metric_card', MetricCardBlock);
registerBlock('empty_state', EmptyStateBlock);
registerBlock('form_panel', FormPanelBlock);
registerBlock('detail_panel', DetailPanelBlock);
registerBlock('activity_timeline', ActivityTimelineBlock);
registerBlock('tabbed_panel', TabbedPanelBlock);
registerBlock('workflow_progress', WorkflowProgressBlock);
// WordPress i18n resolver
const wpResolver = async (key: string) => {
return wp.i18n.__(key, 'your-plugin-textdomain');
};
// Render (inside Inertia setup)
<I18nProvider asyncResolver={wpResolver}>
<ContractPage contract={contract} />
</I18nProvider>wp.i18n
WordPress ships wp.i18n globally when you enqueue the wp-i18n script dependency. The resolver wraps __() for MIDDAG's async interface.
Do NOT use registerDefaults() in IIFE builds
registerDefaults() registers all blocks including lazy-loaded ones that pull in @xyflow/react, @dnd-kit, and other large dependencies. With inlineDynamicImports: true (required for WordPress enqueue), these get inlined into the bundle even if unused. Use selective registration to keep the bundle lean.
Vite IIFE config
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
build: {
outDir: '../assets/dist',
rollupOptions: {
output: {
format: 'iife',
entryFileNames: 'app.js',
inlineDynamicImports: true,
},
},
},
});Asset enqueuing
With IIFE output, enqueue the single app.js file directly — no manifest needed.
WP Admin Chrome
WordPress admin has a fixed chrome that MIDDAG renders within:
- Admin bar — 32px fixed top bar with site links, user menu, and notifications
- Admin sidebar — 160px wide (collapses to 36px on narrow screens or when toggled)
- Content area — MIDDAG renders here, to the right of the WP sidebar and below the admin bar
CSS custom properties are set automatically by the host adapter:
--host-header-height: 32px; /* WP admin bar */
--host-sidebar-width: 160px; /* WP sidebar (expanded) */
--host-sidebar-width: 36px; /* WP sidebar (collapsed) */The WP admin bar and sidebar are permanent
The WordPress admin bar and sidebar are always visible in the admin area. Design your MIDDAG pages within their frame — never attempt to hide or override them.
PHP Controller
Register a WordPress admin page and render the contract via Inertia:
// your-plugin.php
add_menu_page(
'MIDDAG',
'MIDDAG',
'manage_options',
'middag',
function() {
$contract = [
'version' => '1',
'shell' => 'product',
'page' => [
'key' => 'dashboard',
'title' => __('Dashboard', 'your-plugin'),
],
'layout' => [
'template' => 'stack',
'regions' => [
'content' => [
// Your blocks here
],
],
],
];
// Render via Inertia
wp_middag_render('Dashboard', [
'contract' => $contract,
]);
}
);wp_middag_render
The wp_middag_render() helper handles Inertia response setup, shared props injection, and asset enqueuing. It mirrors what $this->inertia() does in the Moodle framework.
Host Theme Detection
MIDDAG automatically detects the WordPress admin color scheme and adapts:
- Dark mode detection — reads
body.admin-color-*classes to determine the active color scheme - Known schemes —
admin-color-default,admin-color-light,admin-color-modern, etc. are mapped to light/dark mode - Manual override — users can toggle appearance mode via the sidebar footer toggle, overriding auto-detection
- CSS variables — MIDDAG's design tokens adapt to the host theme via
data-themeattribute on the root element
Appearance toggle
The sidebar footer includes an appearance toggle (sun/moon icon) that lets users switch between light and dark mode regardless of the WordPress admin scheme.