Docs/Guides/Plugins

Plugin route trees

@veap/plugins/router exports route-tree contracts and discovery/matching helpers. The plugin contract permits routeTree to be a route node or a function returning one…

2 min read

@veap/plugins/router exports route-tree contracts and discovery/matching helpers. The plugin contract permits routeTree to be a route node or a function returning one synchronously/asynchronously.

Route tree contract#

A plugin can return the route tree from a plugin-owned app/ directory using discoverRoutes(). Keep the directory scoped to that plugin so route discovery cannot accidentally load another plugin's files.

ts
import type { IPlugin } from "@veap/plugins";

export const plugin: IPlugin = {
  manifest: {
    id: "reports",
    name: "Reports",
    version: "1.0.0",
    enabled: true,
  },
  async routeTree() {
    const { discoverRoutes } = await import("@veap/plugins/router");
    const path = await import("node:path");
    const appDir = path.join(process.cwd(), "plugins/reports/src/app");

    return discoverRoutes(appDir, (relativePath) =>
      import(`../src/app/${relativePath}`),
    );
  },
};

This is a pattern sketch: the loader callback's module path must match your bundler and project layout. Dynamic import paths are subject to bundler constraints; compile and test the actual route discovery in your application before publishing a plugin.

Test the route surface#

At minimum, verify:

  • static and dynamic segments resolve to the intended handler;
  • nested layouts and error/loading boundaries behave as expected;
  • middleware calls next() correctly and handles thrown errors;
  • route access checks run on the server;
  • plugin disablement removes or blocks the plugin's routes according to the host integration.

The plugin router is not a replacement for Next.js's own App Router. Use the host's documented integration layer and do not assume native Next.js routes are automatically intercepted.

veap
Preparing0%