MyronCMS Developers Hub Docs sandbox review

Build Extensions

Add An Extension Admin Route

An extension admin route adds a human-facing screen under the authenticated MyronCMS admin app. Use it for setup panels, diagnostics, or extension-owned management UI.

Admin routes are not actions. They do not appear in MCP tools/list, and an installed MCP client cannot call them as tools. The AI-supported path is local file authoring in the repository.

Goal

Create a local route at:

/x/my_vendor/settings

from an extension package at:

app/extensions/my_vendor/

Prerequisites

  • You are working in the MyronCMS repository.
  • The extension has a valid manifest.json.
  • The operator can register and enable the extension.
  • The route is intended for an authenticated administrator in the browser.

Human Path

Add an adminRoutes entry to manifest.json:

{
  "vendor": "my_vendor",
  "name": "My Vendor",
  "version": "0.1.0",
  "requiredScopes": ["administration.read"],
  "hasMigrations": false,
  "adminRoutes": [
    {
      "key": "settings",
      "path": "admin/routes/settings.php"
    }
  ]
}

Create the route file:

app/extensions/my_vendor/admin/routes/settings.php

Use the admin shell helpers:

<?php

declare(strict_types=1);

require_once dirname(__DIR__, 4) . '/system/bootstrap.php';

$currentUser = myronRequireAdministrationAccess();
$sdk = new MyronExtensionSDK('my_vendor');

myronRenderAdminShellStart($currentUser, [
    'title' => 'My Vendor Settings',
    'titleContext' => 'Extensions',
    'activeItem' => 'settings',
]);
?>
<div class="mc-workspace__header">
  <?php myronRenderAdminBreadcrumbs([
      ['label' => 'Extensions', 'href' => myronBuildAdminUrl('extensions.installed')],
      ['label' => 'My Vendor Settings'],
  ]); ?>
  <div class="mc-workspace__title-row">
    <h1 class="mc-workspace__title">My Vendor Settings</h1>
  </div>
  <p class="mc-workspace__subtitle">Manage settings owned by this extension.</p>
</div>

<div class="mc-page-canvas mc-page-canvas--site">
  <div class="sg-main">
    <section class="sg-section">
      <h2 class="sg-section__title">Runtime</h2>
      <dl class="sg-define-list">
        <dt>Vendor</dt><dd><code><?= myronEscape($sdk->getVendor()) ?></code></dd>
        <dt>Site type</dt><dd><code><?= myronEscape($sdk->getSiteType()) ?></code></dd>
      </dl>
    </section>
  </div>
</div>
<?php myronRenderAdminShellEnd(); ?>

After the operator registers and enables the extension, MyronCMS mounts the route during loader boot.

AI Path

An AI coding agent can create or edit:

  • app/extensions/my_vendor/manifest.json
  • app/extensions/my_vendor/admin/routes/settings.php

The agent should then run verification and report the local route that will be mounted after the extension is registered and enabled.

An installed MCP client cannot create route files, register the route as a tool, or force the loader to mount it. If an agent is operating through MCP only, the safe output is an implementation plan or a parity note, not a runtime route change.

Route Mapping

ExtensionManifest.php requires each route entry to have:

FieldConstraint
keyKebab-case style: starts with a lowercase letter and contains lowercase letters, numbers, underscores, or hyphens.
pathRelative path under the extension directory. It must not be empty, contain .., or start with /.

ExtensionLoader mounts existing handler files under:

/x/{vendor}/{tail}

The route tail comes from key. If the key repeats the vendor slug or the vendor short name, the loader strips that prefix. For example:

VendorKeyMounted path
my_vendorsettings/x/my_vendor/settings
my_vendormy-vendor-settings/x/my_vendor/settings
my_vendorvendor-settings/x/my_vendor/settings

Scopes

Admin route files do not have action-level requiredScope metadata. Access is controlled by the admin route itself, usually with:

$currentUser = myronRequireAdministrationAccess();

The extension still must pass the loader grant gates. If the manifest declares administration.read, the operator grant must include administration.read before the extension loads.

Artifacts

Local files:

  • app/extensions/my_vendor/manifest.json
  • app/extensions/my_vendor/admin/routes/settings.php

Runtime surface:

  • /x/my_vendor/settings

Source references:

  • app/extensions/myron-sample/admin/routes/hello.php
  • app/system/extensions/ExtensionManifest.php
  • app/system/extensions/ExtensionLoader.php
  • app/system/routing/AppFrontController.php

Safety Boundary

Do not document extension admin routes as MCP-callable tools. If an extension needs AI-callable behavior, expose a scoped MyronAction separately.

Do not skip myronRequireAdministrationAccess() for privileged admin UI. Do not use admin route files to mutate core tables, alter core shell navigation, or bypass extension registration and scope grants.

Do not use absolute route paths or paths that escape the extension directory. The manifest validator rejects those shapes.

Verification

Run:

php app/tests/verify-extension-system-foundation.php

For the reference extension, the test verifies that:

  • the sample extension route is registered at /x/myron_sample/hello,
  • extensions.register resolves,
  • extensions.installed resolves,
  • the sample extension URL key resolves to x/myron_sample/hello.

For a new route, verify that:

  1. the manifest parses,
  2. the extension is registered and enabled,
  3. required manifest scopes are granted,
  4. the handler file exists at the manifest path,
  5. the browser route loads for an administrator.

Failure Modes

FailureLikely surfaceSafe fix
Extension adminRoutes entries must be objects.Manifest parse.Use objects with key and path.
Extension admin route keys must be kebab-case.Manifest parse.Use a lowercase route key such as settings.
Extension admin route paths must be relative paths.Manifest parse.Use admin/routes/settings.php, not /admin/... or ../....
Route is not mountedLoader route registration.Confirm the extension is registered, enabled, granted, and the handler file exists.
Browser route redirects or forbids accessAdmin access gate.Sign in as an administrator; do not weaken the route guard.
Route absent from MCP tools/listExpected behavior.Admin routes are browser UI; create a scoped action for AI-callable behavior.