Getting Started
Get up and running with MIDDAG React UI in under five minutes.
Quick Start (recommended)
Run the wizard from your plugin project root:
npx create-middag-uiThe wizard:
- Detects your host — finds
version.php(Moodle) orwp-config.php(WordPress) - Asks for target directory — default
ui/, or pass as argument:npx create-middag-ui mydir - Configures registry — npm public (no auth) or GitHub Packages (with source, needs token)
- Scaffolds config + demo files — package.json, tsconfig, Vite config, custom block example, standalone component
- Runs npm install — automatically installs all dependencies
- Shows next steps — how to start the dev server and integrate with your platform
After the wizard completes:
cd ui
npm run dev:mock # Opens at http://localhost:5174You should see a working admin page with a "Setup Complete" metric card and an example data table. That's your first PageContract rendering.
What's next after the wizard?
The generated mock/hello-contract.ts is your starting point. Edit it to match your plugin's real pages, then connect to your backend. See CLI docs for all available commands.
Manual Install
If you prefer to set things up yourself instead of using the wizard:
Option A: npm public registry (no auth needed)
# Install the compiled package directly from npm
npm install @middag-io/react react react-dom @inertiajs/react @inertiajs/coreOption B: GitHub Packages (includes TypeScript source)
# Configure GitHub Packages in your global ~/.npmrc
echo "@middag-io:registry=https://npm.pkg.github.com" >> ~/.npmrc
echo "//npm.pkg.github.com/:_authToken=YOUR_GITHUB_TOKEN" >> ~/.npmrc
# Install the package with full source
npm install @middag-io/react react react-dom @inertiajs/react @inertiajs/coreCreate a token at github.com/settings/tokens with the read:packages scope. See Authentication for details.
Which option?
npm public gives you the compiled library and type definitions. Works for most projects. GitHub Packages additionally includes the TypeScript source for IDE navigation into library internals. Requires a GitHub token with read:packages scope.
Peer dependencies
react >= 19, react-dom >= 19, @inertiajs/react >= 2, and @inertiajs/core >= 2 are required. If you're already using Inertia.js, these are included.
Import & Register
Call registerDefaults() once at your app entry point to populate the shell, layout, and block registries with the built-in components:
// main.tsx
import { registerDefaults } from '@middag-io/react';
import '@middag-io/react/style.css';
// Register all built-in shells, layouts, and blocks
registerDefaults();Wrap with Providers
Wrap your app root with the required providers:
// App.tsx
import { I18nProvider } from '@middag-io/react';
function App({ children }) {
return (
<I18nProvider
locale="en"
resolve={(key) => translations[key] ?? key}
>
{children}
</I18nProvider>
);
}Inertia integration
When using Inertia.js, the providers are typically set up in your app.tsx boot file. The shared props from the backend automatically feed navigation, auth, and flash data.
Render ContractPage
Pass a PageContract object to ContractPage and it handles the rest -- resolving the shell, layout, and blocks from the registries:
// MyPage.tsx
import { ContractPage } from '@middag-io/react';
import type { PageContract } from '@middag-io/react';
const contract: PageContract = {
version: '1',
shell: 'product',
page: {
key: 'users',
title: 'Users',
breadcrumbs: [
{ label: 'Home', href: '/' },
{ label: 'Users' },
],
},
layout: {
template: 'stack',
regions: {
content: [
{
type: 'dense_table',
key: 'users-table',
data: {
columns: [
{ key: 'name', label: 'Name' },
{ key: 'email', label: 'Email' },
],
rows: [
{ id: '1', cells: { name: 'Alice', email: '[email protected]' } },
],
},
},
],
},
},
};
export default function UsersPage() {
return <ContractPage contract={contract} />;
}Send Contract from Backend
In Moodle, use the Inertia adapter to send the contract as page props:
// PHP -- Moodle Controller
return $this->inertia->render('ContractPage', [
'contract' => [
'version' => '1',
'shell' => 'product',
'page' => [
'key' => 'users',
'title' => get_string('users', 'local_myplugin'),
'breadcrumbs' => [
['label' => 'Home', 'href' => '/'],
['label' => get_string('users', 'local_myplugin')],
],
],
'layout' => [
'template' => 'stack',
'regions' => [
'content' => [
[
'type' => 'dense_table',
'key' => 'users-table',
'data' => $table_data,
],
],
],
],
],
]);WordPress
The same contract shape works with WordPress through the host adapter system. The backend just needs to output the PageContract JSON.
What's Next
Now that you have a working setup, explore the rest of the documentation:
- CLI Reference -- all 5 commands: init, doctor, dev, add-block, upgrade
- Page Contracts -- understand the anatomy of shells, layouts, and regions
- Block Reference -- all 16 block types with data shapes and examples
- Moodle Integration -- full Moodle plugin setup guide
- WordPress Integration -- WordPress admin plugin setup guide