milpa / admin
The administration panel of the Milpa PHP framework: a discoverable section shell over the plugin, settings and routing surfaces a host exposes — server-rendered, no JavaScript required.
Requires
- php: >=8.3
- guzzlehttp/psr7: ^2.6
- milpa/auth: ^0.2
- milpa/command: ^0.2
- milpa/core: ^0.6
- milpa/data: ^0.2
- milpa/http: ^0.1.5
- milpa/http-symfony: ^0.1
- milpa/live: ^0.2
- milpa/live-tui: ^0.3
- milpa/live-web: ^0.2
- milpa/plugin: ^0.3
- milpa/runtime: ^0.5
- milpa/tool-runtime: ^0.6
- psr/log: ^3
- symfony/http-foundation: ^7.4
- symfony/psr-http-message-bridge: ^7.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.65
- milpa/container: ^0.1
- phpstan/phpdoc-parser: ^2.3
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^11.5
README
Milpa Admin
The administration panel of the Milpa PHP framework — a section shell that discovers what your app can actually do, server-rendered, no JavaScript required.
Add one plugin to your app and /milpa/admin exists: a navigation, a settings form, a plugin
manager, and a route inspector — behind your own auth, rendered on the server.
Install
composer require milpa/admin
// config/plugins.php return [ Milpa\Admin\AdminPlugin::class, // ... ];
The one idea
The panel knows no section by name. It asks every booted plugin for its sections and renders what it gets back:
final class BillingPlugin implements PluginInterface, AdminSectionProvider { public function adminSections(): array { return [new AdminSection('billing', 'Facturación', '/milpa/admin/billing', 40)]; } }
That is the whole extension point. Your section appears in the navigation, in order, with no change
to this package — and the same list drives the terminal shell (coa:admin, coa:tui), so a
section you add is a section you can also inspect without a browser.
What it ships with
| Section | What it does |
|---|---|
| Settings | The site configuration, as a form generated from the schema of a governed tool — with CSRF, validation, and redisplay of what you typed when it is rejected. |
| Plugins | What your app has, what boots, and a button per row. It drives milpa/plugin's operations, so the panel and coa plugins.list cannot disagree. |
| Sistema | The route table, read-only. |
What a host has to provide
Nothing is assumed and nothing is faked. A capability you did not wire simply does not appear — there are no dead controls (that is a rule, not a habit: see ADR-0005, surface honesty).
| You register | You get |
|---|---|
SessionStore + milpa/auth's scope middleware |
The panel at all — every section is behind milpa.admin. |
PluginRegistryInterface |
The Plugins section: list, enable, disable. |
PluginInstallerInterface |
Install, update and remove on top of it. Without it those three operations do not exist, so no surface renders a button that fails when pressed. |
RouteTableSource |
The Sistema section. Every host builds its route table differently; this port is how yours gets in. |
No JavaScript required
Every control is a real <form> with a real submit. The panel enhances with JS when it is there and
works identically when it is not — which matters most at the exact moment you need it: turning off
the plugin that broke the page is not the time to depend on that page's JavaScript.
Two more decisions worth knowing:
- Installing is not consenting to run. A freshly installed plugin arrives disabled.
- A plugin declared in your code cannot be removed from the panel — it would delete files your own source still names. The panel says so, and offers to disable it instead.
Requirements
- PHP ≥ 8.3
milpa/core^0.6 ·milpa/auth^0.2 ·milpa/command^0.2 ·milpa/data^0.2milpa/http^0.1.5 ·milpa/http-symfony^0.1 ·milpa/runtime^0.5milpa/plugin^0.3 — the operations the Plugins section drivesmilpa/live-web^0.1 ·milpa/live-tui^0.2 ·milpa/tool-runtime^0.6
Contributing
Contributions are welcome — see CONTRIBUTING.md. Please report security issues via SECURITY.md, and note that this project follows a Code of Conduct.
License
Apache-2.0 © Rodrigo Vicente - TeamX Agency.
Milpa is designed, built, and maintained by Rodrigo Vicente - TeamX Agency.