Content Engine

Plugin Frontend Modules

How plugins export AdminCP navigation, Content Engine screens, and runtime configs with optimized code splitting.

To keep the AdminCP sidebar light while lazy-loading heavy rich text editors on demand, plugins separate frontend code into three clean modules.

The Three Frontend Modules

ModuleLocationPurpose
admin/navsrc/admin/nav.tsxLightweight sidebar navigation entries and Lucide icons
admin/contentsrc/admin/content.tsxContent Engine editing screens, custom fields, and form layouts
configsrc/config.tsxMaster plugin definition mounted in host app vitnode.config.ts

1. admin/nav.tsx (Sidebar Navigation)

Kept deliberately minimal so the AdminCP shell loads navigation without pulling in heavy editing components:

plugins/blog/src/admin/nav.tsx
import type { AdminNavPluginSource } from "@vitnode/core/lib/plugin"
import { FileTextIcon } from "lucide-react"
import { postContentType } from "@/content/post"

export const postNav = {
  definition: postContentType,
  icon: <FileTextIcon />,
}

export const adminNav = {
  pluginId: "blog",
  contentTypes: [postNav],
} satisfies AdminNavPluginSource

2. admin/content.tsx (Editing Screens & Overrides)

Loaded only when an administrator navigates into Content Engine screens:

plugins/blog/src/admin/content.tsx
import { contentTypeAdmin } from "@vitnode/core/lib/plugin"
import { postNav } from "./nav"

export const adminContent = {
  pluginId: "blog",
  contentTypes: [
    contentTypeAdmin({
      ...postNav,
      // Optional field or layout overrides
    }),
  ],
}

3. config.tsx (Root Plugin Config)

Exports the main plugin factory used by host applications:

plugins/blog/src/config.tsx
import { buildPlugin } from "@vitnode/core/lib/plugin"
import messages from "./locales"
import { routes } from "./routes/manifest"
import { adminContent } from "./admin/content"

export const blogPlugin = () =>
  buildPlugin({
    pluginId: "blog",
    messages,
    routes,
    contentTypes: adminContent.contentTypes,
  })

Package Exports Configuration

Declare the subpaths in your plugin's package.json:

plugins/blog/package.json
{
  "exports": {
    "./config": "./dist/src/config.js",
    "./admin/nav": "./dist/src/admin/nav.js",
    "./admin/content": "./dist/src/admin/content.js"
  }
}

Learn More