Plugins
The design of Frontdoor's plugin host, its manifest and module contracts, and the packages it accepts. Currently locked off.
On this page
The plugin platform is locked off in current releases: plugin routes answer
404and the server keeps the plugin setting off. This page describes the design.
Frontdoor can load plugins at runtime through a lightweight host. Plugins run in the page origin, so only reviewed, owner-approved code should ever be enabled.
Loader inputs
Set one or more of these variables before building or deploying:
| Variable | Value |
|---|---|
VITE_FRONTDOOR_PLUGIN_MANIFESTS |
Manifest URLs, as a comma-separated or newline-separated list |
VITE_FRONTDOOR_PLUGIN_MODULES |
Module URLs, as a comma-separated or newline-separated list |
VITE_FRONTDOOR_ENABLE_SAMPLE_PLUGIN |
Boolean flag that loads the built-in ticket example |
Manifest contract
{
"id": "ticket-plugin",
"name": "Ticket Plugin",
"version": "1.0.0",
"description": "Adds a ticket creation action, route and surface",
"entry": "https://cdn.example.com/ticket-plugin/index.js",
"permissions": ["actions.write", "routes.write"],
"roles": ["owner", "admin"],
"backend": {
"enabled": true,
"url": "https://plugins.example.com/frontdoor-webhook",
"eventSubscriptions": ["auth.login", "app.access"]
}
}
Module contract
A module exports a register(api) function. The SDK also offers definePlugin() and definePluginManifest() helpers for canonical metadata and plugin definitions.
import { definePlugin, definePluginManifest } from '../pluginHost/sdk.js';
export const manifest = definePluginManifest({
id: 'ticket-plugin',
name: 'Ticket Plugin',
version: '1.0.0',
});
export function register(api) {
api.registerAction({
id: 'create-ticket',
label: 'Create Ticket',
surface: 'layout.accountMenu',
order: 20,
onClick: () => api.notify({ type: 'success', message: 'Ticket flow opened' }),
});
}
export default definePlugin({
manifest,
register,
});
Runtime API
The plugin host exposes:
getCurrentUser()getBranding()getLanguage()getUiStrings()navigate()notify()openExternalUrl()registerAction()registerSurface()registerRoute()registerNavigationItem()
Surfaces
Built-in surfaces where a plugin can add content:
layout.nav.desktoplayout.nav.mobilelayout.accountMenuhome.hero.afterhome.controls.afterhome.catalog.afteradmin.header.actionsadmin.page.topadmin.page.bottomcustomization.page.topcustomization.page.bottom
Server registry
Frontdoor can store plugin metadata in SQLite and expose it through /api/plugins. The runtime loader reads /api/plugins/runtime and loads every enabled plugin that has a frontend entry. The admin page shows the server registry separately from the in-memory runtime snapshot.
Install and approve
From the admin page you can install a plugin by filling in the manifest fields, pasting a module source, uploading a single JSON package, or pointing to an external entry URL. New installs are pending until an owner approves them.
The same page can export the current draft as a JSON package and open a validation wizard before installation or approval. The wizard shows the package's risk level, the permissions it requires, its backend webhook exposure and the raw package.
Backend events
A plugin can receive backend events by declaring backend.url and backend.eventSubscriptions. Events are dispatched only to plugins that are both enabled and approved.
Package formats
JSON package
A single JSON file with a manifest object and an optional moduleSource string. The module source must be self-contained and export register(api) directly.
{
"manifest": {
"id": "ticket-plugin",
"name": "Ticket Plugin",
"version": "1.0.0",
"permissions": ["actions.write", "routes.write", "surfaces.write"],
"roles": ["owner", "admin"]
},
"moduleSource": "export function register(api) { api.registerRoute({ id: 'ticket-plugin.route', path: '/plugins/ticket-center', label: 'Ticket Center' }); } export default { register };"
}
ZIP package
A ZIP archive with this structure, suited to third-party plugins distributed as a single bundle:
my-plugin-1.0.0/
manifest.json
module.mjs
The admin page can import and export plugins in this format.
Audit trail
Plugin approvals and revocations are recorded in the audit log with target type plugin, so owners can review who approved or rejected a package. The dedicated view is at /admin/plugins/audit.