Server mode
Run the docs as a Next server so private docs, Ask AI, MCP and real redirects work on Vercel, a container or any Node host.
In server mode the docs app is a running Next server instead of a folder of files. A proxy.ts file sees every request first, so it can sign readers in, gate pages and answer Ask AI. Use it when you need those features and don't serve the docs from your Nest app.
When to use server mode
| You need | Static | Server mode |
|---|---|---|
Private docs (access) | Not enforced | Enforced on every request |
Ask AI and the MCP servers (ai) | Hidden | Served |
Wildcard redirects (/old/*) | Netlify and Cloudflare only | Real HTTP redirects everywhere |
| Cheapest hosting | Yes | Needs a Node runtime |
If your Nest app already serves the docs, you don't need server mode. mountOrbitDocs enforces access and serves Ask AI from the static build.
Turn it on
Set the mode:
export default defineConfig({
// …
output: { mode: 'server', basePath: '' },
});Keep proxy.ts in the docs app root. orbitdocs init creates it:
import { orbitProxy } from '@orbitdocs/next/proxy';
export default orbitProxy();
export const config = {
matcher: ['/((?!_next/static|_next/image).*)'],
};Build:
npx orbitdocs buildThe CLI prints Server build in .next (start with `next start`).
Start it from the docs app folder, with the secrets in the environment:
ORBITDOCS_AUTH_SECRET=$(openssl rand -hex 32) npx next start -p 3001What proxy.ts does
orbitProxy() reads two files that orbitdocs build writes: .orbitdocs/access.json (from access) and .orbitdocs/ai.json (from ai). For each request it:
- Returns 404 for
orbitdocs-access.jsonandorbitdocs-ai.json, so the manifests are never served. - Answers Ask AI (
/_ai/*) and MCP (/mcp,/mcp/<api id>) when the config hasai. - Answers sign-in routes (
/_auth/*) when the config hasaccess. - Gates the page. Readers without access are sent to the login page.
- Lets the request through to Next.
Without access and ai, it lets every request through. A site with neither section can keep the file.
Options
| Option | Type | Default | What it does |
|---|---|---|---|
appDir | string | process.cwd() | Folder that holds .orbitdocs/. Set it when next start runs from another folder. |
publicUrl | string | The request's origin | Public origin, such as https://docs.acme.com, when a proxy in front rewrites the Host header. Used for sign-in callback URLs. |
export default orbitProxy({ publicUrl: 'https://docs.acme.com' });Ship the .orbitdocs folder
The proxy reads .orbitdocs/access.json and .orbitdocs/ai.json at runtime. Copy that folder along with .next/ wherever you run the server.
Without it the proxy finds no rules and serves every page.
Environment variables
Secrets are read from the server's environment at request time, never from the build:
| Variable | Needed for |
|---|---|
ORBITDOCS_AUTH_SECRET (or your access.session.secretEnv) | Signing reader sessions. 32 or more characters. |
Each provider's clientSecretEnv | SSO sign-in. |
jwtSecretEnv, secretKeyEnv of appSession | Some app-session adapters. |
access.personalization.secretEnv | Signing the personalization hook call. |
ai.apiKeyEnv | Ask AI and MCP. |
The full list with defaults is on Environment variables.
Run it in a container
The CLI's docker target only covers static builds. For server mode, build first and copy the docs app into a Node image:
FROM node:22-bookworm-slim
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
ENV NODE_ENV=production
EXPOSE 3000
CMD ["npx", "next", "start", "-p", "3000"]node_modules
outThe image installs its own node_modules so native packages match Linux. .next/, openapi/ and .orbitdocs/ come from your build.
cd docs
npx orbitdocs build # writes .next/, openapi/ and .orbitdocs/
docker build -t acme-docs .
docker run -p 3000:3000 -e ORBITDOCS_AUTH_SECRET=… acme-docsBuild on the host or in CI, not inside the image: extraction needs your Nest app, which is outside the docs folder.
Differences from a static build
- Redirects are real
301/302responses, wildcards included. - URLs keep their trailing slash (
/quickstart/), the same as static. orbitdocs deployaccepts only--target vercelin this mode.orbitdocs publishrefuses server builds. The platform hosts static builds and adds its own server.

