Skip to content

Next.js

Next.js support is for static export builds.

Install OpenNav in your Next.js project.

Terminal window
npm install @opennav-ai/opennav

Quick start

import { OpenNavNext } from "@opennav-ai/opennav/next";
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
output: "export",
};
export default OpenNavNext({
siteName: "Example Docs",
siteUrl: "https://example.com",
mode: "static",
})(nextConfig);

This is all you need for the standard Next static export folder. OpenNav reads out after next build and writes the generated AI Web Compatibility Layer files there.

Full example

import { OpenNavNext } from "@opennav-ai/opennav/next";
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
output: "export",
distDir: "dist",
};
export default OpenNavNext({
siteName: "Example Docs",
siteUrl: "https://example.com",
mode: "static",
platform: "cloudflare-pages",
contentExtraction: {
stripLayout: true,
},
accessGuidance: {
contentSignals: {
search: "allow",
aiInput: "allow",
aiTrain: "disallow",
},
},
})(nextConfig);

OpenNav follows distDir automatically, so the example above reads and writes dist without repeating that path inside OpenNavNext(...).

Most projects should leave outputDirectory out of OpenNavNext(...). OpenNav uses the same folder Next uses for the static export.

Next configOpenNav scans
output: "export"out
output: "export", distDir: "dist"dist
output: "export", distDir: "public-build/"public-build

Pass outputDirectory only when OpenNav should read a different relative folder than the one configured for the Next static export.

Wraps a Next.js config object and runs OpenNav after supported static export builds.

interface OpenNavNextOptions {
readonly siteName: string;
readonly siteUrl: string;
readonly mode?: "static";
readonly outputDirectory?: string;
readonly platform?: "cloudflare-pages";
readonly contentExtraction?: {
readonly stripLayout?: boolean;
};
readonly staticHeaders?: {
readonly enabled: boolean;
};
readonly accessGuidance?: {
readonly contentSignals?: {
readonly search?: "allow" | "disallow";
readonly aiInput?: "allow" | "disallow";
readonly aiTrain?: "allow" | "disallow";
};
};
}

Required. Human-readable site or docs name written into generated OpenNav files, including llms.txt, page Markdown files, and .well-known/opennav.json inside the static export folder.

Required. Public absolute URL used for generated links and manifest URLs. The value should include the protocol and host, such as https://example.com.

Optional. Only "static" is supported today, and OpenNav uses it when mode is omitted.

OpenNav runs only when the wrapped Next config uses output: "export".

Optional. Static export folder OpenNav scans and updates after next build. Defaults to the wrapped Next config’s distDir when it is a string, then falls back to out.

Use this only when OpenNav should read a different folder than the one configured for the Next static export. Relative paths are resolved from the working directory that runs next build, so monorepo setups can use paths such as apps/docs/out. Absolute paths are rejected, and trailing slashes are handled automatically.

Optional. Static hosting platform for platform-specific generated files.

Supported values are "cloudflare-pages". When platform: "cloudflare-pages" is passed, OpenNav creates or updates _headers inside the static export folder by default so Cloudflare Pages serves generated Markdown, llms files, and the OpenNav manifest with explicit response content types. The same _headers block also adds per-page HTTP Link headers to HTML routes so agents can discover each page’s Markdown alternate and the root llms.txt index from response headers.

Omit platform for a generic Next static export build. More platform values will be added as OpenNav gains first-class support for additional static hosts.

export default OpenNavNext({
siteName: "Example Docs",
siteUrl: "https://example.com",
platform: "cloudflare-pages",
})(nextConfig);

Optional. Controls how OpenNav reads built HTML pages before creating generated Markdown page artifacts and llms-full.txt.

When omitted, OpenNav preserves the current conservative behavior: it converts the whole HTML <body> to Markdown. Set stripLayout to true to remove the documented fixed list of layout elements before Markdown conversion.

See the content extraction reference for the exact stripped elements and the cases where you should leave this unset.

This first version uses a fixed strip list. Future versions are expected to add more granular HTML element controls, such as tag-level, class-level, or selector-level strip and preserve rules.

export default OpenNavNext({
siteName: "Example Docs",
siteUrl: "https://example.com",
contentExtraction: {
stripLayout: true,
},
})(nextConfig);

Optional. Defaults to false.

When true, OpenNav still starts from the whole HTML <body>, but removes the declared layout elements before converting that body to Markdown.

Optional. Controls platform response-header artifacts such as Cloudflare Pages _headers.

When omitted, OpenNav uses the configured platform default. The current Cloudflare Pages default is enabled, so platform: "cloudflare-pages" creates or updates _headers in the static export folder unless you opt out.

If an existing caller-owned _headers route overlaps OpenNav’s generated routes, OpenNav leaves _headers untouched and reports a warning.

export default OpenNavNext({
siteName: "Example Docs",
siteUrl: "https://example.com",
platform: "cloudflare-pages",
staticHeaders: {
enabled: false,
},
})(nextConfig);

Required inside staticHeaders. Set to false to keep platform metadata such as platform: "cloudflare-pages" without creating or editing the platform header file. Set to true to explicitly request the platform header file. When true, platform must also be configured because each host has its own header-file format.

Optional. Controls whether OpenNav creates or updates its managed Content Signals block in the static export folder’s robots.txt.

When omitted, OpenNav does not create or edit robots.txt for access guidance.

Optional. Content-use preferences OpenNav writes into the static export folder’s robots.txt.

At least one nested field must be configured before OpenNav creates or updates its managed Content Signals block.

search

Optional. Writes search=yes for “allow” or search=no for “disallow”. When omitted, OpenNav does not express a search-use preference.

aiInput

Optional. Writes ai-input=yes for “allow” or ai-input=no for “disallow”. When omitted, OpenNav does not express an AI-input preference.

aiTrain

Optional. Writes ai-train=yes for “allow” or ai-train=no for “disallow”. When omitted, OpenNav does not express an AI-training preference.

Next.js server output is the next open-source track. This is the future of agent-ready websites: the same route can serve HTML to people and Markdown to agents through content negotiation.

Planned launch shape:

import { OpenNavNextServer } from "@opennav-ai/opennav/next/server";
import type { NextRequest } from "next/server";
const opennav = OpenNavNextServer({
siteName: "Example Docs",
markdown: {
mode: "content-negotiation",
routes: ["/docs/:path*", "/blog/:path*"],
},
});
export function proxy(request: NextRequest) {
return opennav.handle(request);
}
export const config = {
matcher: ["/docs/:path*", "/blog/:path*"],
};

When a request prefers text/markdown, OpenNav will return an agent-readable Markdown representation from the same URL. Browser requests still receive HTML, and responses include Vary: Accept so caches keep both representations correct.

See the server-side framework roadmap for the shared Astro and Next.js launch shape.