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.

Maintainers

Package info

github.com/getmilpa/admin

pkg:composer/milpa/admin

Transparency log

Statistics

Installs: 2

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.1.0 2026-07-28 01:21 UTC

This package is auto-updated.

Last update: 2026-07-28 01:21:20 UTC


README

Milpa

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.

CI Packagist PHP License

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

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.