Next.js
`@multitenant/next`, `next-app`, `next-pages` — meta package, App Router, Pages Router.
Next.js — Meta package
Meta-package for App Router apps: re-exports @multitenant/core, @multitenant/config, @multitenant/react, and @multitenant/next-app so you can depend on one scope for typical Next.js setups.
Install
npm install @multitenant/next next react react-domWhen to use
- Prefer
@multitenant/nextwhen you want one install line and tree-shaking still keeps bundles reasonable. - Use
@multitenant/next-appalone if you only need the middleware/server surface and already depend on core separately.
Next.js — App Router
Next.js App Router integration: middleware for Edge-safe tenant resolution (headers), plus server helpers to read x-tenant-key, x-market-key, and related headers. Subpaths /auto and /auto-node re-export config-aware shortcuts.
Use @multitenant/next-app (or @multitenant/next). Keep middleware Edge-safe (static JSON / small bundle); put DB in Route Handlers, Server Actions, or RSC with runtime = 'nodejs' when needed.
Install
npm install @multitenant/next-app next react react-domPeers: next, and typically @multitenant/core for createTenantRegistry.
Main APIs
createTenantMiddleware(registry, options?)— sets resolution headers;onMissingTenant:'passthrough'|'warn'|'throw'getTenantFromHeaders,requireTenant— in Server Components / Route Handlers /nodejsruntime
Resolution vs data access
| Runtime | Tenant resolution | Database / heavy Node |
|---|---|---|
| Edge middleware | createTenantMiddleware + static config | No |
| Node server | getTenantFromHeaders / requireTenant | Yes — e.g. runWithTenantScope |
Middleware defaults
onMissingTenant: 'passthrough'— avoids throwing on rawlocalhostduringnext dev; usemultitenant dev+domains.localhosts, or'throw'when every request must resolve.- Prefer
x-forwarded-hostbehind a reverse proxy (middleware normalizes the left-most host). - Headers forwarded to the app:
x-tenant-key,x-market-key,x-tenant-env, optionalx-tenant-flags(JSON).
Shared registry module
lib/tenant-registry.ts
import type { TenantsConfig } from '@multitenant/core';
import { createTenantRegistry } from '@multitenant/core';
import tenantsConfig from '../tenants.config.json';
export const tenantRegistry = createTenantRegistry(tenantsConfig as TenantsConfig);
export function multitenantEnv() {
return (process.env.MULTITENANT_ENV ?? process.env.TENANTIFY_ENV ?? 'local') as import('@multitenant/core').EnvironmentName;
}middleware.ts
import { createTenantMiddleware } from '@multitenant/next-app';
import { multitenantEnv, tenantRegistry } from '@/lib/tenant-registry';
export const middleware = createTenantMiddleware(tenantRegistry, {
environment: multitenantEnv(),
});
export const config = {
matcher: ['/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)'],
};Route Handler
import { headers } from 'next/headers';
import { NextResponse } from 'next/server';
import { getTenantFromHeaders } from '@multitenant/next-app';
import { multitenantEnv, tenantRegistry } from '@/lib/tenant-registry';
export async function GET() {
const h = await headers();
const resolved = getTenantFromHeaders(h, tenantRegistry, { environment: multitenantEnv() });
return NextResponse.json({
tenantKey: resolved?.tenantKey ?? null,
marketKey: resolved?.marketKey ?? null,
});
}Server Action
'use server';
import { headers } from 'next/headers';
import { getTenantFromHeaders } from '@multitenant/next-app';
import { multitenantEnv, tenantRegistry } from '@/lib/tenant-registry';
export async function currentTenantKey(): Promise<string | null> {
const h = await headers();
const resolved = getTenantFromHeaders(h, tenantRegistry, { environment: multitenantEnv() });
return resolved?.tenantKey ?? null;
}Use requireTenant when a missing tenant must hard-fail — it throws TenantNotFoundError.
Server Actions & Node-only code
Set export const runtime = 'nodejs' on routes/layouts that use fs, native drivers, or @multitenant/database.
Zero-config shortcut
@multitenant/next-app/auto — createTenantMiddlewareFromConfig(json, { environment }) for a single-file middleware (see Examples — Next.js (App Router)).
Next.js — Pages Router
Next.js Pages Router helpers: getServerSideProps and API route wrappers that attach ResolvedTenant (and market) to the request context.
You typically createTenantRegistry once (e.g. lib/tenant-registry.ts) and pass registry + environment into helpers.
Install
npm install @multitenant/next-pages next react react-domPackage name on npm is next-pages (monorepo folder next-paages).
Main APIs
| Export | Role |
|---|---|
withTenantGSSP | Wrap getServerSideProps — receives context with resolvedTenant (or triggers notFound) |
withTenantApi | Wrap NextApiHandler — req.tenant pattern or JSON errors |
Behaviour when host does not resolve
| API | Result |
|---|---|
withTenantApi | 404 response { error, code: 'MULTITENANT_TENANT_NOT_FOUND' } |
withTenantGSSP | { notFound: true } — Next notFound(); no TenantNotFoundError thrown inside GSSP |
See Errors.
Scaffold
npx @multitenant/cli init --framework next-pagesInstall @multitenant/next-pages, next, react, @multitenant/core.
For the App Router, see Next.js — App Router above.
See also
@multitenant/react— client context from the same headers as App Router- Home — adapters & package map