PermDock
CLI

Next.js plugin

createPermDockPlugin runs permdock collect during next dev and next build; it is a build hook only and never wires the PermDock API.

createPermDockPlugin is exported from permdock/next/plugin and wraps next.config.ts. Its only job is to run collect while Next.js runs, the way next-intl's loader keeps extracted message catalogs in sync during development. It does not alias modules, does not augment types and does not create a PermDock instance. API wiring is the explicit factory file described in the quick start.

Usage

// next.config.ts
import { createPermDockPlugin } from "permdock/next/plugin";

const permdockPlugin = createPermDockPlugin({
  collect: { srcPath: ["./src", "../ui/src", "./node_modules/@acme/*"] },
});

export default permdockPlugin({
  // your Next.js config
});

srcPath accepts first-party folders, sibling workspace packages and installed packages, so a monorepo where @acme/ui ships its own permissions.ts next to its components is collected into the app's catalog without any manual import.

permdockPlugin accepts a config object or a config function and returns Next's config function (phase, context) => Promise<config>: the phase constant is how the plugin tells next build from next dev. Put it outermost when composing with plugins that only accept an object:

export default permdockPlugin(withOtherPlugin({/* your Next.js config */}));

What it does

PhaseBehaviour
next devRuns collect once at startup, then watches each app root the way collect --watch does: srcPath, the config file and the configured modules, ignoring its own outputs. Writes permissions.catalog.json (and the barrel when collect.barrel is enabled). Failures are logged, never fatal.
next buildRuns collect --check. A stale catalog fails the build with the diff, so a deployment can never ship a catalog that disagrees with the code. PERMDOCK_COLLECT=write switches to writing instead of checking for build pipelines that commit generated files.
next start, next exportNothing.

The plugin runs collect in-process from the same permdock package the app already depends on, so there is nothing else to install.

What it does not do

  • It does not provide getPermDock, getPermission or usePermission. Those come from your factory file and from permdock/react.
  • It does not add a webpack or Turbopack alias for a request config module.
  • It does not augment permdock types with your policy or subject.
  • It does not run usage, doctor or openapi; those stay explicit CI steps.

This is deliberate. The alternative, a next-intl-style plugin plus request config plus module augmentation, would have given a package-level import for server helpers at the cost of being Next-only and global to one policy per app. Explicit factories work identically in Vite, Expo and Hono, and agents follow one recipe.

Vite apps use createPermDockUnplugin for the same hook. Expo (Metro) has no build hook; run permdock collect as a script instead.

Options

createPermDockPlugin({
  collect: {
    srcPath: string[]          // required; globs relative to the app root
    out?: string               // default 'permissions.catalog.json'
    barrel?: boolean | string  // default false; true writes src/permissions.generated.ts
  },
  onDrift?: 'error' | 'warn'   // build behaviour on a stale catalog; default 'error'
  check?: boolean              // unplugin only: check instead of write in buildStart; default false
})

Settings can also live in permdock.config.ts; plugin options override the file.

Turbopack

Next.js 16.3 builds with Turbopack by default. The plugin does not register a loader or a Turbopack rule; it hooks Next's config lifecycle and runs the collector as a side process, so it works with Turbopack and webpack alike and has no effect on the module graph or on the App Shell used by Instant Navigations (Next.js 16.3 research).

Example

apps/examples/next uses the plugin. apps/examples/monorepo collects from two sibling feature packages with permdock collect --check and fails CI on catalog drift.

Why

  • The dev-time catalog stays at the app root, not in .next/. The catalog is a committed file that collect --check compares in CI, that permdock usage, openapi and cloud push read, and that reviewers see in a diff. Writing it into .next/ during next dev would give the same data two homes, one of them deleted by every next build and invisible to tools that do not know about Next.js.

Last updated on

On this page