nextjs-cms

Using Plugins

Plugins add pages and API routes to the admin. Install a package, register it in cms.config.ts, and grant access.

Installing a plugin

Three steps. Using the cache-revalidation plugin as the example:

1. Install the package

Terminal
pnpm add @nextjscms/plugin-cache-revalidation

2. Register it in cms.config.ts

cms.config.ts
import { cacheRevalidationPlugin } from '@nextjscms/plugin-cache-revalidation'
import { defineConfig } from 'nextjs-cms/core/config'

export default defineConfig({
    plugins: [
        // Short form: just the descriptor
        cacheRevalidationPlugin,
    ],
})

3. Register its page component

Plugin pages are rendered by the admin's catch-all plugin route. Map the plugin's name to its server entry:

app/(rootLayout)/(plugins)/[...slug]/plugin-server-registry.ts
export const pluginNamesMap: Record<string, string> = {
    plugin_cache_revalidation: '@nextjscms/plugin-cache-revalidation/server',
    // A workaround to avoid importing errors if no plugins are installed
    blank: 'nextjs-cms/plugins/blank-component',
}

The key is the plugin's name: its package name @nextjscms/plugin-<slug> becomes plugin_<slug_with_underscores>.

If the plugin ships styled components, make sure Tailwind scans it:

app/globals.css
@source '../node_modules/@nextjscms/plugin-*/**/*.{tsx,ts,jsx,js}';

Then grant admins access: each plugin appears in the privileges list on the Admins page (the Master admin gets it automatically).

Configuring a plugin

Use the long form to pass options, rename it, or change its icon:

cms.config.ts
plugins: [
    {
        plugin: cacheRevalidationPlugin,
        options: {
            contentTypes: ['posts', 'categories'],
            skipInDevelopment: true,
        },
        override: {
            title: { en: 'Site cache', ar: 'ذاكرة الموقع' },
            icon: 'refresh-cw',
        },
    },
]
KeyTypeDescription
plugindescriptorThe plugin, as exported by its package.
optionsRecord<string, unknown>Passed to the plugin's createPlugin(options). See each plugin's README.
override.titlestring | Record<locale, string>Rename the sidebar entry.
override.iconLucide icon nameChange the sidebar icon.
override.routes{ [path]: { title?, icon? } }Per-page overrides for plugins with several pages. Keys are type-checked against the plugin's routes.
groupRoutesbooleanFor plugins with several pages: show them as a collapsible group (default true) or as separate sidebar items.

How override applies:

Plugin shapegroupRoutesoverride.title / iconoverride.routes[path]
One pageignoredRenames the pageRenames the page (redundant)
Several pagestrue (default)Renames the sidebar groupRenames one page
Several pagesfalseNo effect (a warning is logged)Renames one page

Using a plugin page as the dashboard

Replace the default dashboard with any plugin page. It becomes visible to all signed-in admins, regardless of privileges:

cms.config.ts
dashboard: { override: '/cache-revalidation' },

Official plugins

Cache revalidation

@nextjscms/plugin-cache-revalidation keeps a cached Next.js website in sync with the CMS. It sends a revalidation request to your site on every create, update, and delete, retries failures, records what never landed, and gives you a page to retry, dismiss, or purge.

sections/posts.section.ts
import { siteRevalidationHooks } from '@nextjscms/plugin-cache-revalidation/hooks'

export default hasItemsSection({
    // ...
    hooks: siteRevalidationHooks('posts'), // cache tag used by your site
})
OptionDefaultDescription
contentTypesrequiredThe cache tags your site uses.
urlEnv'REVALIDATE_URL'Env var with your site's origin.
secretEnv'REVALIDATE_SECRET'Env var with the shared secret.
path'/api/revalidate'Revalidation route on your site.
timeoutMs3000Per-attempt timeout.
attempts2Attempts for retryable failures.
skipInDevelopmentfalseSend nothing unless NODE_ENV === 'production'.

It also needs its dictionaries merged into i18n (see Plugin strings) and a revalidation route on your site. The package README has the full setup.

cPanel dashboard and cPanel emails

@nextjscms/plugin-cpanel-dashboard shows hosting information (disk, bandwidth, and so on) from cPanel. @nextjscms/plugin-cpanel-emails lists and manages the domain's email accounts. Both read these environment variables:

VariableDescription
CPANEL_DOMAINYour cPanel host.
CPANEL_USERcPanel username.
CPANEL_API_TOKENAPI token (preferred).
CPANEL_PASSWORDPassword, used only when no token is set.

Google Analytics

@nextjscms/plugin-google-analytics reserves a Google Analytics page in the admin. It's an early preview.

Troubleshooting

SymptomCause
The plugin isn't in the sidebarThe admin lacks the privilege, or the plugin isn't in cms.config.ts.
The page is blankThe plugin is missing from plugin-server-registry.ts.
The page is unstyledTailwind isn't scanning the plugin package (@source).
Raw keys like revalidationTitle in the UIThe plugin's dictionaries aren't merged into i18n.supportedLanguages.