@intelligo-dev/next
v1.2.0
Published
The Next.js adapter: the one Intelligo package that imports next/*, binding request context, auth routes and Route Handler guards.
Maintainers
Readme
@intelligo-dev/next
The Next.js adapter: the one Intelligo package that imports next/*, binding request context, auth routes and Route Handler guards.
Part of Intelligo, an application framework and
operational platform for vertical AI SaaS products. Every @intelligo-dev/*
package is released at one version and shares one database schema;
pnpm dlx @intelligo-dev/cli create my-app installs the set an
application needs. Documentation:
intelligo.dev/docs/packages/next.
Install
pnpm add @intelligo-dev/nextnext and better-auth are peers: the adapter binds into the copies your
application already has.
Use
Tell the framework where a request's headers come from — once, from the composition root:
// lib/intelligo.ts
import {
setBackgroundTaskRunner,
setRequestContextSource,
} from "@intelligo-dev/core/request-context";
import { nextBackgroundTasks, nextRequestContext } from "@intelligo-dev/next";
setRequestContextSource(nextRequestContext);
setBackgroundTaskRunner(nextBackgroundTasks);nextBackgroundTasks hands the work the framework starts without awaiting it
— auth emails, a new workspace's bootstrap, notification emails — to Next's
after(), so a serverless host keeps the function alive until it finishes.
Mount Better-Auth's HTTP handlers:
// app/api/auth/[...all]/route.ts
export { GET, POST } from "@intelligo-dev/next/auth";Guard a Route Handler. The wrapper resolves the caller first and answers a
failed check itself — 401 without a session, 403 without a workspace or
the role, with { "error": <code> } as the body. What the handler throws
propagates unchanged:
// app/api/invoices/route.ts
import { withRole } from "@intelligo-dev/next/route";
export const GET = withRole(
["owner", "admin"],
async (request, { workspace }) =>
Response.json(await listInvoices(workspace.id))
);withAuth needs only a session, withWorkspace an active workspace. Next's
own second argument — a dynamic segment's params — arrives third, typed by
the wrapper's parameter (Next's generated RouteContext<"/api/invoices/[id]">
fits there too):
// app/api/invoices/[id]/route.ts
export const DELETE = withWorkspace<{ params: Promise<{ id: string }> }>(
async (request, { workspace }, { params }) => {
const { id } = await params;
await deleteInvoice(workspace.id, id);
return new Response(null, { status: 204 });
}
);ActionResult<T> is the shape a Server Action returns to its form —
{ success: true, data } or { success: false, error } — shared by every
registry item's actions:
import type { ActionResult } from "@intelligo-dev/next";The subpaths are separate so that binding the request context does not load the configured Better-Auth server instance.
Why a package
Every other @intelligo-dev/* package has to be usable from a queue worker, a
Hono API, a test, or a product built on something that is not Next. Keeping
every next/* import in one package — and having an architecture test refuse
it anywhere else — is what makes that true.
Licence
Apache-2.0
