Skip to content

Next.js

@vperms/next targets the Next.js App Router. It can resolve permissions in-process with an adapter, or proxy to a separate vperms server over HTTP.

permissions.ts
import { createNextVPerms, nextBackend } from "@vperms/next";
import { VeguiPermsMemoryAdapter } from "vperms";
export const vperms = createNextVPerms({
backend: nextBackend({
adapter: new VeguiPermsMemoryAdapter(),
workspace: "workspace",
subjectResolver: (request) => request?.headers.get("x-user-id") ?? null,
}),
});

nextBackend resolves entirely inside Next.js — no HTTP hop to a vperms server.

interface NextBackendOptions {
adapter: VeguiPermsAdapter;
workspace: string;
subjectResolver: SubjectResolver;
defaultParents?: DefaultParents;
}

externalBackend points at a deployed vperms HTTP server. Server Components forward cookie and authorization (configurable) to the origin.

import { createNextVPerms, externalBackend } from "@vperms/next";
export const vperms = createNextVPerms({
backend: externalBackend({
origin: "https://api.example.com",
prefix: "/vperms",
subjectResolver: (request) => request?.headers.get("x-user-id") ?? null,
}),
});
interface ExternalBackendOptions {
origin: string;
prefix?: string; // default "/vperms"
subjectResolver?: SubjectResolver;
fetch?: FetchLike;
fetchOptions?: RequestInit;
forwardHeaders?: string[]; // default ["cookie", "authorization"]
}
interface NextVPermsConfig {
backend: Backend;
prefix?: string; // default "/vperms"
client?: "direct" | "proxy"; // default "proxy"
cache?: CacheWrapper;
browserFetchOptions?: RequestInit;
}
  • client: "proxy" (default) routes browser requests through the app’s route handler; "direct" calls the external origin from the browser.
  • cache defaults to React.cache, making resolution request/render-scoped.
import { vperms } from "@/permissions";
export default async function Page() {
const ability = await vperms.getAbility();
return (
<vperms.Provider>
<vperms.Ability permission="admin.read" fallback={<NoAccess />}>
<Dashboard />
</vperms.Ability>
</vperms.Provider>
);
}

The returned NextVPerms exposes getResolvedSubject, getAbility, Provider, Ability and handlers.

Export the built-in handlers to serve the client and the permissions export endpoint:

app/vperms/[...path]/route.ts
import { vperms } from "@/permissions";
export const { GET } = vperms.handlers;

With the local backend the handler authorizes and resolves locally. With the external backend it proxies matching GET /subject/... requests to the origin, stripping host/content-length and disabling redirect following.

"use client";
import { createNextVPerms } from "@vperms/next/client";
export const vperms = createNextVPerms({
origin: "", // "" for same-origin proxy, external origin for "direct"
prefix: "/vperms",
});

@vperms/next/client re-exports everything from @vperms/react/client.

Server: createNextVPerms, nextBackend, externalBackend, NextVPermsConfig, NextVPerms, NextVPermsHandlers, NextRouteContext, BrowserConfig, ClientTransport, SubjectResolver, SubjectResolverResult, NextBackendOptions, ExternalBackendOptions, Backend, plus the React server bindings. Client: createNextVPerms, NextClientConfig and the React client exports.