āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā š nextjs/app/api-reference/config/next-config-js/adapterPath ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā
Next.js provides an experimental API that allows you to create custom adapters to hook into the build process. This is useful for deployment platforms or custom build integrations that need to modify the Next.js configuration or process the build output.
To use an adapter, specify the path to your adapter module in experimental.adapterPath:
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
adapterPath: require.resolve('./my-adapter.js'),
},
}
module.exports = nextConfig
An adapter is a module that exports an object implementing the NextAdapter interface:
export interface NextAdapter {
name: string
modifyConfig?: (
config: NextConfigComplete,
ctx: {
phase: PHASE_TYPE
}
) => Promise<NextConfigComplete> | NextConfigComplete
onBuildComplete?: (ctx: {
routes: {
headers: Array<ManifestHeaderRoute>
redirects: Array<ManifestRedirectRoute>
rewrites: {
beforeFiles: Array<ManifestRewriteRoute>
afterFiles: Array<ManifestRewriteRoute>
fallback: Array<ManifestRewriteRoute>
}
dynamicRoutes: ReadonlyArray<ManifestRoute>
}
outputs: AdapterOutputs
projectDir: string
repoRoot: string
distDir: string
config: NextConfigComplete
nextVersion: string
}) => Promise<void> | void
}
Here's a minimal adapter example:
/** @type {import('next').NextAdapter} */
const adapter = {
name: 'my-custom-adapter',
async modifyConfig(config, { phase }) {
// Modify the Next.js config based on the build phase
if (phase === 'phase-production-build') {
return {
...config,
// Add your modifications
}
}
return config
},
async onBuildComplete({
routes,
outputs,
projectDir,
repoRoot,
distDir,
config,
nextVersion,
}) {
// Process the build output
console.log('Build completed with', outputs.pages.length, 'pages')
// Access different output types
for (const page of outputs.pages) {
console.log('Page:', page.pathname, 'at', page.filePath)
}
for (const apiRoute of outputs.pagesApi) {
console.log('API Route:', apiRoute.pathname, 'at', apiRoute.filePath)
}
for (const appPage of outputs.appPages) {
console.log('App Page:', appPage.pathname, 'at', appPage.filePath)
}
for (const prerender of outputs.prerenders) {
console.log('Prerendered:', prerender.pathname)
}
},
}
module.exports = adapter
modifyConfig(config, context)Called for any CLI command that loads the next.config to allow modification of the configuration.
Parameters:
config: The complete Next.js configuration objectcontext.phase: The current build phase (see phases)Returns: The modified configuration object (can be async)
onBuildComplete(context)Called after the build process completes with detailed information about routes and outputs.
Parameters:
routes: Object containing route manifests for headers, redirects, rewrites, and dynamic routes
routes.headers: Array of header route objects with source, sourceRegex, headers, has, missing, and optional priority fieldsroutes.redirects: Array of redirect route objects with source, sourceRegex, destination, statusCode, has, missing, and optional priority fieldsroutes.rewrites: Object with beforeFiles, afterFiles, and fallback arrays, each containing rewrite route objects with source, sourceRegex, destination, has, and missing fieldsroutes.dynamicRoutes: Array of dynamic route objects with source, sourceRegex, destination, has, and missing fieldsoutputs: Detailed information about all build outputs organized by typeprojectDir: Absolute path to the Next.js project directoryrepoRoot: Absolute path to the detected repository rootdistDir: Absolute path to the build output directoryconfig: The final Next.js configuration (with modifyConfig applied)nextVersion: Version of Next.js being usedbuildId: Unique identifier for the current buildThe outputs object contains arrays of different output types:
outputs.pages)React pages from the pages/ directory:
{
type: 'PAGES'
id: string // Route identifier
filePath: string // Path to the built file
pathname: string // URL pathname
sourcePage: string // Original source file path in pages/ directory
runtime: 'nodejs' | 'edge'
assets: Record<string, string> // Traced dependencies (key: relative path from repo root, value: absolute path)
wasmAssets?: Record<string, string> // Bundled wasm files (key: name, value: absolute path)
config: {
maxDuration?: number
preferredRegion?: string | string[]
env?: Record<string, string> // Environment variables (edge runtime only)
}
}
outputs.pagesApi)API routes from pages/api/:
{
type: 'PAGES_API'
id: string
filePath: string
pathname: string
sourcePage: string // Original relative source file path
runtime: 'nodejs' | 'edge'
assets: Record<string, string>
wasmAssets?: Record<string, string>
config: {
maxDuration?: number
preferredRegion?: string | string[]
env?: Record<string, string>
}
}
outputs.appPages)React pages from the app/ directory with page.{js,ts,jsx,tsx}:
{
type: 'APP_PAGE'
id: string
filePath: string
pathname: string // Includes .rsc suffix for RSC routes
sourcePage: string // Original relative source file path
runtime: 'nodejs' | 'edge'
assets: Record<string, string>
wasmAssets?: Record<string, string>
config: {
maxDuration?: number
preferredRegion?: string | string[]
env?: Record<string, string>
}
}
outputs.appRoutes)API and metadata routes from app/ with route.{js,ts,jsx,tsx}:
{
type: 'APP_ROUTE'
id: string
filePath: string
pathname: string
sourcePage: string
runtime: 'nodejs' | 'edge'
assets: Record<string, string>
wasmAssets?: Record<string, string>
config: {
maxDuration?: number
preferredRegion?: string | string[]
env?: Record<string, string>
}
}
outputs.prerenders)ISR-enabled routes and static prerenders:
{
type: 'PRERENDER'
id: string
pathname: string
parentOutputId: string // ID of the source page/route
groupId: number // Revalidation group identifier (prerenders with same groupId revalidate together)
pprChain?: {
headers: Record<string, string> // PPR chain headers (e.g., 'x-nextjs-resume': '1')
}
parentFallbackMode?: 'blocking' | false | null // Fallback mode from getStaticPaths
fallback?: {
filePath: string
initialStatus?: number
initialHeaders?: Record<string, string | string[]>
initialExpiration?: number
initialRevalidate?: number
postponedState?: string // PPR postponed state
}
config: {
allowQuery?: string[] // Allowed query parameters
allowHeader?: string[] // Allowed headers for ISR
bypassFor?: RouteHas[] // Cache bypass conditions
renderingMode?: RenderingMode
bypassToken?: string
}
}
outputs.staticFiles)Static assets and auto-statically optimized pages:
{
type: 'STATIC_FILE'
id: string
filePath: string
pathname: string
}
outputs.middleware)Middleware function (if present):
{
type: 'MIDDLEWARE'
id: string
filePath: string
pathname: string // Always '/_middleware'
sourcePage: string // Always 'middleware'
runtime: 'nodejs' | 'edge'
assets: Record<string, string>
wasmAssets?: Record<string, string>
config: {
maxDuration?: number
preferredRegion?: string | string[]
env?: Record<string, string>
matchers?: Array<{
source: string
sourceRegex: string
has: RouteHas[] | undefined
missing: RouteHas[] | undefined
}>
}
}
The routes object in onBuildComplete provides complete routing information with processed patterns ready for deployment:
Each header route includes:
source: Original route pattern (e.g., /about)sourceRegex: Compiled regex for matching requestsheaders: Key-value pairs of headers to applyhas: Optional conditions that must be metmissing: Optional conditions that must not be metpriority: Optional flag for internal routesEach redirect route includes:
source: Original route patternsourceRegex: Compiled regex for matchingdestination: Target URL (can include captured groups)statusCode: HTTP status code (301, 302, 307, 308)has: Optional positive conditionsmissing: Optional negative conditionspriority: Optional flag for internal routesRewrites are categorized into three phases:
beforeFiles: Checked before filesystem (including pages and public files)afterFiles: Checked after pages/public files but before dynamic routesfallback: Checked after all other routesEach rewrite includes source, sourceRegex, destination, has, and missing.
Generated from dynamic route segments (e.g., [slug], [...path]). Each includes:
source: Route patternsourceRegex: Compiled regex with named capture groupsdestination: Internal destination with parameter substitutionhas: Optional positive conditionsmissing: Optional negative conditionsCommon use cases for adapters include:
ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā