Extensions
CairnCMS is built to be extended. The same APIs and components that power the platform are available to you, so a custom extension can add new capabilities without forking the codebase.
This page covers the extension types CairnCMS ships with and how to choose between them. The next page, Creating extensions, covers the toolchain — scaffolding, building, installing, and publishing.
Extension types
Section titled “Extension types”CairnCMS supports nine extension types, grouped into four categories.
App extensions
Section titled “App extensions”App extensions extend the admin app. They are written as Vue components and run in the browser.
- Interface — a custom field editing widget. Use this to add new ways to enter or edit data on the item form.
- Display — a custom read-only renderer for a field. Use this when you need a different way to show a value in lists, tables, and detail views without changing how it is edited.
- Layout — a custom collection page layout, alongside the built-in Table, Cards, Calendar, and Map.
- Module — a brand-new top-level area in the module bar. Use this when you need an entire workspace that does not fit into the existing modules.
- Panel — a custom panel type for Insights dashboards.
API extensions
Section titled “API extensions”API extensions extend the server. They are written in JavaScript or TypeScript and run in Node.
- Hook — a way to react to or modify platform events. Hooks come in four flavours:
filter(blocking, can transform or veto),action(non-blocking, runs after),init(runs once at startup), andschedule(runs on a cron schedule). - Endpoint — a custom HTTP route mounted alongside the built-in API. Use this when you need to expose logic that does not map to a collection’s CRUD endpoints.
Hybrid extensions
Section titled “Hybrid extensions”Hybrid extensions have both an app component and a server component.
- Operation — a custom flow operation. The app side renders the operation’s configuration form in the flow editor; the API side runs the logic when the flow executes.
Bundle
Section titled “Bundle”- Bundle — a wrapper that ships several extensions of any type as a single package. Use this when several extensions share dependencies, are released together, or implement a single coherent feature across the app and API.
Choosing an extension type
Section titled “Choosing an extension type”A short decision rubric:
- The user needs a new way to edit a field’s value → Interface.
- The user needs a new way to display a field’s value in non-edit contexts → Display.
- The user needs a new way to browse a whole collection → Layout.
- The user needs an entirely new workspace unrelated to existing modules → Module.
- A dashboard needs a new visualization or interaction → Panel.
- The server needs to react to or modify a platform event → Hook.
- The server needs to expose a custom HTTP route → Endpoint.
- A flow needs a new step → Operation.
- Several extensions ship together → Bundle.
If you find yourself wanting to ship app and server logic that should be released together, reach for a Bundle rather than separate top-level extensions.
Convention-based customization (not extensions)
Section titled “Convention-based customization (not extensions)”A couple of developer-facing customization paths exist outside the extension system. They use simple file-folder conventions rather than the SDK’s define* API:
- Custom migrations — drop migration
.jsfiles intoEXTENSIONS_PATH/migrationsand they run alongside built-in migrations. - Email templates — drop Liquid templates into
EXTENSIONS_PATH/templatesand reference them from the Send Email flow operation or by name from any code that sends mail.
These are not extension types and do not require the SDK or a build step. They are documented separately for that reason.
Installation
Section titled “Installation”CairnCMS discovers extensions from three sources:
- Package extensions — installed from npm into the project’s
node_modules. Any package whose name matchescairncms-extension-<name>,@<scope>/cairncms-extension-<name>, or@cairncms/extension-<name>is auto-discovered. - Local package extensions — full package directories (each with its own
package.json) placed insideEXTENSIONS_PATH. Bundles are installed this way. - Local file extensions — pre-built extension files placed in type subfolders inside
EXTENSIONS_PATH(for example,EXTENSIONS_PATH/interfaces/<name>/index.js). Used for non-bundle extension types when you do not need a separate package.
The Creating extensions page walks through all three.
Where to go next
Section titled “Where to go next”- Creating extensions covers the toolchain end to end: scaffold, build, install, hot reload, publish.
- The individual type pages above cover each extension type’s API, file structure, and minimum example.