Frontend extensions let you change how the Calagopus panel looks and behaves in the browser. A single extension can add entirely new pages, inject components into existing pages, register routes in any section of the panel, override Mantine theme tokens, and provide custom translation strings — all without modifying the panel’s source code.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/calagopus/panel/llms.txt
Use this file to discover all available pages before exploring further.
How frontend extensions are loaded
When the panel starts, it compiles each uploaded extension’s frontend code alongside the core panel bundle. At runtime, every loaded extension is instantiated as anExtension class and passed to a shared ExtensionContext. The context calls initialize on each extension in order, then merges all ExtensionRegistry instances together. From that point forward, the panel reads route and component registrations from the merged registry.
initialize or initializeMantineTheme, the error is logged to the browser console and the remaining extensions continue loading.
The Extension class
Your extension must export a default class that extendsExtension from the shared package.
frontend/src/index.ts (or .tsx) file of your extension archive must contain export default — the panel’s validator checks for this before accepting the upload.
The ExtensionRegistry
Insideinitialize, you use ctx.extensionRegistry to register all UI contributions. The registry is organized into four top-level namespaces, each with typed entry methods:
| Namespace | Purpose |
|---|---|
pages | Add or modify components on specific panel pages |
routes | Register new URL routes in any section |
elements | Hook into shared elements such as the Monaco editor |
global | Inject components that render on every page |
Registering routes
Theroutes sub-registry exposes methods for each route group:
Injecting components into pages
Thepages namespace gives you fine-grained access to individual panel pages. Server pages, admin pages, and dashboard pages are each represented by a typed registry class.
Server pages example — injecting a stat card into the console:
console, files, databases, subusers, backups, network, startup, mounts, settings, activity.
Server console extensions
The console registry offers the most injection points. In addition to stat cards, you can inject components next to the power buttons, in the terminal header, and in the terminal input row:File manager extensions
The file manager registry lets you add toolbar buttons, context menu items, custom file icons, and entirely new editor actions:Theming
Return a partialMantineThemeOverride from initializeMantineTheme to override any Mantine design tokens. Multiple extension theme overrides are deep-merged in load order:
Translations
UsedefineTranslations to add i18n strings scoped to your extension namespace:
Inter-extension calls
Extensions can call into each other at runtime usingctx.call. The call iterates through all loaded extensions until one returns a non-skip value:
ctx.skip() for calls that do not belong to your extension.
Extension archive structure
A valid extension archive (.c7s.zip) must contain:
Metadata.toml format:
Installing a frontend extension
Check the heavy image requirement
Frontend extension installation uses the same upload and rebuild pipeline as backend extensions. You must use
ghcr.io/calagopus/panel:heavy.Upload the archive
Navigate to Admin → Extensions and upload the
.c7s.zip file. The panel validates that frontend/src/index.ts (or .tsx) contains export default.Rebuild
Trigger a rebuild from the Extensions panel. The frontend bundle is recompiled with the extension included.
Configuration UI
If your extension needs admin-configurable settings, setcardConfigurationPage to a React component. This component is rendered at /admin/extensions/<packageName> and linked from the extension’s card on the Extensions overview page. Use it to display and save settings that your backend extension exposes through its settings deserializer.
Utility: hookable components and functions
Theshared package exports makeComponentHookable and makeFunctionHookable for wrapping existing panel components or functions so extensions can intercept their props or return values without replacing them entirely.
Related
- Extensions overview — the heavy image requirement, archive format, and rebuild process
- Auth provider extensions — backend extension lifecycle and settings API