cdk-nextjs 0.7.12 → 0.7.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.jsii +237 -81
- package/.jsii.tabl.json +1 -1
- package/API.md +152 -0
- package/README.md +115 -100
- package/docs/breaking-changes.md +4 -2
- package/docs/development-guide.md +10 -0
- package/lib/adapter/adapter.mjs +4 -1
- package/lib/generated-structs/OptionalNextjsDistributionProps.d.ts +21 -0
- package/lib/generated-structs/OptionalNextjsDistributionProps.js +1 -1
- package/lib/nextjs-api.js +1 -1
- package/lib/nextjs-build/nextjs-build.js +1 -1
- package/lib/nextjs-cache.js +1 -1
- package/lib/nextjs-compute/nextjs-containers.js +1 -1
- package/lib/nextjs-compute/nextjs-functions.js +1 -1
- package/lib/nextjs-distribution.d.ts +71 -2
- package/lib/nextjs-distribution.js +156 -107
- package/lib/nextjs-distribution.test.js +361 -12
- package/lib/nextjs-post-deploy.js +1 -1
- package/lib/nextjs-static-assets.js +1 -1
- package/lib/nextjs-static-assets.test.js +19 -7
- package/lib/root-constructs/nextjs-base-construct.js +1 -1
- package/lib/root-constructs/nextjs-global-containers.d.ts +16 -1
- package/lib/root-constructs/nextjs-global-containers.js +4 -2
- package/lib/root-constructs/nextjs-global-functions.d.ts +16 -1
- package/lib/root-constructs/nextjs-global-functions.js +4 -2
- package/lib/root-constructs/nextjs-regional-containers.js +1 -1
- package/lib/root-constructs/nextjs-regional-functions.js +1 -1
- package/lib/runtime/lambda.mjs +4 -1
- package/lib/runtime/server.mjs +4 -1
- package/lib/utils/viewer-request-functions.d.ts +53 -0
- package/lib/utils/viewer-request-functions.js +172 -0
- package/lib/utils/viewer-request-functions.test.d.ts +1 -0
- package/lib/utils/viewer-request-functions.test.js +43 -0
- package/package.json +4 -1
- package/scripts/e2e-harness/app.js +7 -2
- package/scripts/render-diagrams.mjs +121 -0
package/.jsii
CHANGED
|
@@ -9032,7 +9032,7 @@
|
|
|
9032
9032
|
},
|
|
9033
9033
|
"name": "cdk-nextjs",
|
|
9034
9034
|
"readme": {
|
|
9035
|
-
"markdown": "\n[](https://www.npmjs.org/package/cdk-nextjs)\n\n\n# CDK Next.js Construct Library\n\n<!--BEGIN STABILITY BANNER-->\n\n---\n\n\n\n> The APIs of higher level constructs in this module are experimental and under active development.\n> They are subject to non-backward compatible changes or removal in any future version. These are\n> not subject to the [Semantic Versioning](https://semver.org/) model and breaking changes will be\n> announced in the release notes. This means that while you may use them, you may need to update\n> your source code when upgrading to a newer version of this package.\n\n---\n\n<!--END STABILITY BANNER-->\n\nDeploy [Next.js](https://nextjs.org/) apps on [AWS](https://aws.amazon.com/) with the [AWS CDK](https://aws.amazon.com/cdk/).\n\n## Features\n\n- Supports all features of Next.js App and Pages Router for [Node.js Runtime](https://nextjs.org/docs/app/building-your-application/rendering/edge-and-nodejs-runtimes#nodejs-runtime).\n- Choose your AWS architecture for Next.js with the supported constructs: `NextjsGlobalFunctions`, `NextjsGlobalContainers`, `NextjsRegionalContainers`, `NextjsRegionalFunctions`.\n- Global Content Delivery Network (CDN) built with [Amazon CloudFront](https://aws.amazon.com/cloudfront/) to deliver content with low latency and high transfer speeds.\n- Serverless functions powered by [AWS Lambda](https://aws.amazon.com/lambda/) or serverless containers powered by [AWS Fargate](https://aws.amazon.com/fargate/).\n- Static assets (JS, CSS, public folder) are stored and served from [Amazon Simple Storage Service (S3)](https://aws.amazon.com/s3/) for all constructs (except `NextjsRegionalContainers`) to decrease latency and reduce compute costs by serving directly from S3.\n- [Optimized images](https://nextjs.org/docs/pages/building-your-application/optimizing/images), [data cache](https://nextjs.org/docs/app/building-your-application/caching#data-cache), [full route cache](https://nextjs.org/docs/app/building-your-application/caching#full-route-cache) and [`'use cache: remote'`](https://nextjs.org/docs/app/api-reference/directives/use-cache-remote) are shared across compute with [Amazon Simple Storage Service (S3)](https://aws.amazon.com/s3/) with supporting metadata in [Amazon DynamoDB](https://aws.amazon.com/dynamodb), and `revalidateTag`/`revalidatePath` reach plain [`'use cache'`](https://nextjs.org/docs/app/api-reference/directives/use-cache) on every instance. See [`'use cache'` and `'use cache: remote'`](#use-cache-and-use-cache-remote).\n- Customize every construct via `overrides`.\n- AWS security and operational best practices are utilized, guided by [cdk-nag](https://github.com/cdklabs/cdk-nag).\n- First class support for [monorepos](https://monorepo.tools/).\n- [Bring Your Own Resources](#bring-your-own-resources) — import existing AWS resources (CloudFront distributions, ECS clusters, ALBs, S3 buckets, DynamoDB tables).\n- [AWS GovCloud (US)](https://aws.amazon.com/govcloud-us) compatible with `NextjsRegionalFunctions` and `NextjsRegionalContainers`.\n\n## Prerequisites\n\n- Next.js app running v16.3 or higher (`next build` fails on older versions). If you don't have one yet - follow [these steps](https://nextjs.org/docs/getting-started) to create one.\n- [AWS Cloud Development Kit](https://docs.aws.amazon.com/cdk/v2/guide/home.html) app either in the same package or separate package. cdk-nextjs supports monorepos.\n- A Docker compatible container engine, but **only** for `NextjsGlobalContainers` and `NextjsRegionalContainers` - we recommend [Rancher Desktop](https://rancherdesktop.io/) with dockerd (moby). The two Functions types deploy zip Lambdas and need no container engine.\n- [Node.js](https://nodejs.org/en) v24 (or LTS)\n\n## Getting Started\n\n1. Install `cdk-nextjs` in the package(s) containing your CDK and Next.js app with `npm i cdk-nextjs`\n2. Deploy your Next.js app to AWS: `cdk deploy`. Make sure you have [AWS credentials](https://docs.aws.amazon.com/cli/v1/userguide/cli-chap-configure.html) configured.\n3. Visit URL printed in terminal (CloudFormation Output) to view your Next.js app!\n\nNo `next.config` change is needed: cdk-nextjs runs `next build` itself, and sets [`NEXT_ADAPTER_PATH`](https://nextjs.org/docs/app/api-reference/config/next-config-js/adapterPath) on that build so Next.js loads cdk-nextjs's [Deployment Adapter](https://nextjs.org/docs/app/guides/deployment-adapters).\n\n### Registering the adapter yourself\n\nSet `adapterPath` in `next.config` in three cases. An explicit `adapterPath` always wins over `NEXT_ADAPTER_PATH`, so this is also how you pin a specific adapter.\n\n- **cdk-nextjs isn't running your build** — `skipBuild: true`, or you build in CI and hand the output to CDK.\n- **cdk-nextjs isn't a dependency of the Next.js app**, only of the CDK app. cdk-nextjs resolves the adapter from your app's directory, so it can't find it in that layout.\n- **cdk-nextjs is linked from outside your project root** — a `link:`/`file:` dependency on a checkout elsewhere on disk, as this repo's own examples use. The symlink resolves out of the project, and the adapter derives its cache handler path from its own location, so Next.js gets a `cacheHandler` outside `turbopack.root` and Turbopack rejects it. Setting `adapterPath` fixes this because the build resolves it, after whatever put the adapter in place.\n\n```ts\nimport { NextConfig } from \"next\";\n\nconst nextConfig: NextConfig = {\n // ...\n adapterPath: require.resolve(\"cdk-nextjs/adapter\"),\n};\n\nexport default nextConfig;\n```\n\n`require.resolve` works in an ESM `next.config.ts` too, because Next.js transpiles the config to CJS before evaluating it.\n\n### cdk-nextjs Created Dockerfile\n\nFor the Containers types, cdk-nextjs generates a Dockerfile in your Next.js app's directory. It cannot clean the file up after the image is built, so either commit it or gitignore it.\n\nEvery generated Dockerfile starts with the line `# ~~ Generated by cdk-nextjs ~~`, and cdk-nextjs **overwrites** any file carrying it — that way an upgrade that changes how the image is built does not leave a stale Dockerfile behind. To customize it, delete that first line; cdk-nextjs then leaves the file alone. If you edited a generated file without deleting the header, cdk-nextjs saves your version beside it as `<name>.Dockerfile.bak` before replacing it; gitignore that too.\n\n## Basic Example CDK App\n\n```ts\nimport { App, Stack, StackProps } from \"aws-cdk-lib\";\nimport { Construct } from \"constructs\";\nimport { NextjsGlobalFunctions } from \"cdk-nextjs\";\nimport { join } from \"node:path\";\n\nclass WebStack extends Stack {\n constructor(scope: Construct, id: string, props?: StackProps) {\n super(scope, id, props);\n new NextjsGlobalFunctions(this, \"Nextjs\", {\n buildDirectory: join(import.meta.dirname),\n });\n }\n}\n\nconst app = new App();\n\nnew WebStack(app, \"web-stack\");\n```\n\nSee [examples/](./examples/) for more usage examples.\n\n## Configuration\n\nThe variables below are read at runtime by the cache handler inside your deployed\nLambda functions or containers. Set them on the compute through `overrides`:\n\n```ts\n// NextjsGlobalFunctions / NextjsRegionalFunctions\noverrides: {\n nextjsFunctions: {\n functionProps: { environment: { CDK_NEXTJS_MEMORY_CACHE_TTL_MS: \"0\" } },\n },\n},\n\n// NextjsGlobalContainers / NextjsRegionalContainers\noverrides: {\n nextjsContainers: {\n taskImageOptions: { environment: { CDK_NEXTJS_MEMORY_CACHE_TTL_MS: \"0\" } },\n },\n},\n```\n\nValues you pass are merged over the ones the construct sets, so the same mechanism\noverrides the [infrastructure variables](#infrastructure-configuration) too.\n\n### Cache Configuration\n\n#### `CDK_NEXTJS_MEMORY_CACHE_TTL_MS`\n\nTime to live in milliseconds for in-memory cache entries. After this duration, entries expire and are removed from the cache.\n\n**Note**: Every memory hit is checked against the tag revalidation markers, so an entry revalidated on another instance is not served from memory. A tag's marker is read from DynamoDB only on its first use and a rolling re-read every few minutes; in between, revalidations arrive through the revalidation log (one `Query` per [`CDK_NEXTJS_TAG_REFRESH_MS`](#cdk_nextjs_tag_refresh_ms)). Memory still saves the S3 read and body parse. Set this to `0` to disable the memory cache entirely (all requests will fall through to S3 + DynamoDB).\n\n**Default**: `3600000` (1 hour)\n\n**Examples**:\n\n- Short TTL (5 minutes): `300000` - for frequently changing data\n- Medium TTL (1 hour): `3600000` - balanced between freshness and performance\n- Long TTL (24 hours): `86400000` - for mostly static content\n\n**Trade-offs**:\n\n- Lower values: More cache misses, fresher data, higher S3/DynamoDB costs\n- Higher values: Fewer cache misses, better performance, but longer stale data windows\n\n#### `CDK_NEXTJS_MEMORY_CACHE_MAX_ENTRIES`\n\nMaximum number of cache entries to store in memory. When this limit is reached, the least recently used (LRU) entry is evicted.\n\n**Default**: `1000`\n\n**Examples**:\n\n- Small cache: `100` - minimal memory footprint for simple apps\n- Medium cache: `1000` - good balance for typical applications\n- Large cache: `10000` - for high-traffic apps with many unique pages\n\n**Trade-offs**:\n\n- Lower values: Less memory usage, more cache evictions\n- Higher values: More memory usage, fewer cache evictions, better hit rates\n\n**Memory considerations**: Each entry stores the full cache value (HTML, JSON, etc.). A typical page cache might be 10-100KB, so 1000 entries ≈ 10-100MB of memory. Consider your compute environment's memory limits (Lambda: 128MB-10GB, Fargate: 512MB-30GB) and size accordingly.\n\n### `'use cache'` and `'use cache: remote'`\n\nThe adapter registers two [`cacheHandlers`](https://nextjs.org/docs/app/api-reference/config/next-config-js/cacheHandlers)\nnext to the `cacheHandler` it already sets, unless your `next.config` names a\nhandler of its own for either:\n\n| Directive | `cacheHandlers` name | Stored | Tags |\n| --------------------- | -------------------- | -------------------------------- | ----------------------- |\n| `'use cache'` | `default` | each instance's memory | DynamoDB, all instances |\n| `'use cache: remote'` | `remote` | S3 cache bucket, memory in front | DynamoDB, all instances |\n\n- **`'use cache: remote'`** is shared: an entry any instance generates is the one\n every instance serves, until it expires or a tag is revalidated. Use it for\n results you don't want each Lambda instance or task to compute on its own. It\n costs an S3 `GetObject` the first time an instance reads an entry, and a\n `PutObject` per generated entry. Objects live under\n `<buildId>/_use-cache/` in the cache bucket and are pruned with the build.\n- **`'use cache'`** stays per instance, as Next.js intends — but `revalidateTag`,\n `updateTag` and `revalidatePath` now expire it on every instance, not only the\n one that ran them. Next.js's built-in handler keeps tags in process memory, so\n before this every other instance kept serving the revalidated value, even into\n pages re-rendered because of that revalidation.\n\nBoth read the same per-tag marker rows in the revalidation table that ISR and\nthe data cache use. A tag an instance has not seen yet — an entry read from S3,\na page's implicit `revalidatePath` tags — is read from its marker before it is\ntrusted, once per instance.\n\nAfter that, an instance doesn't re-read the tags it tracks to learn what\nchanged. Each `revalidateTag`/`updateTag` also writes a row to a revalidation\nlog in the same table (`pk = <buildId>#log`, expiring after 15 minutes through\nthe table's `ttl` attribute). At most once per\n[`CDK_NEXTJS_TAG_REFRESH_MS`](#cdk_nextjs_tag_refresh_ms),\neach instance sends one DynamoDB `Query` for the rows written since its last\none and applies those for tags it tracks. So a revalidation on another instance\nis honored within that window (1 second by default), and on the instance that ran\nit immediately. An idle instance's query costs 0.5 RCU a second, where\nre-reading up to 1000 tracked tags cost about 500. Each tag's marker is still\nre-read every 7.5 to 10 minutes, a few each second rather than all at once (about 8\nRCU a second at the most an instance tracks, 10,000 tags). After a gap the log\nmay no longer cover (a Lambda frozen between invocations, a run of failed\nqueries), an instance forgets its tracked markers and reads each again as it's\nneeded. ISR and the data cache share the same copy of the markers, so one\n`revalidateTag` writes each tag's rows once and one `Query` serves them all.\n\nIf you pass your own `revalidationTable`, enabling TTL on its `ttl` attribute is\nrecommended. Without it the log rows (about 100 bytes per revalidated tag) are\nkept until a deploy replaces their build, whose post-deploy step deletes them.\n\nTwo instances that generate the same `'use cache: remote'` entry at the same\nmoment both store it; each serves its own copy until that copy's `revalidate`\ntime, after which S3's is used.\n\n#### `CDK_NEXTJS_TAG_REFRESH_MS`\n\nHow often, at most, in milliseconds, an instance asks the revalidation log what\nother instances revalidated, for `'use cache'`, ISR and the data cache alike. A\n`revalidateTag` elsewhere goes unseen for up to about the window plus a second\n(2 s by default), since `'use cache'` doesn't wait for the answer - and for\nlonger while a query is slow or failing, or for a page render that started\ninside the window, which reads what the instance knew when it began. It's one DynamoDB `Query`,\nhowever many tags the instance tracks, shared by every request on the instance\nduring the window. `0` asks before every cache check, and waits for the answer\n(`'use cache'` only while the instance holds an entry the answer could expire).\nOtherwise `'use cache'` reads don't wait for it, and it applies from the\ninstance's next request. The exception is an instance that hasn't caught up for\nover a second past the window (it sat idle or was frozen): it waits for the\nanswer, before rendering the page for a page request. `'use cache: remote'`\nalways waits.\n\n**Default**: `1000`\n\n#### `CDK_NEXTJS_USE_CACHE_MEMORY_BYTES`\n\nSize bound, in bytes, of each handler's in-memory store: all of `'use cache'`,\nand the memory tier in front of S3 for `'use cache: remote'`. Least recently used\nentries are evicted first.\n\n**Default**: `52428800` (50 MB, Next.js's own default)\n\n### Infrastructure Configuration\n\nThe construct sets these itself and they typically don't need to be modified:\n\n#### `CDK_NEXTJS_BUILD_ID`\n\nUnique identifier for the Next.js build. Used for cache isolation between deployments.\n\n#### `CDK_NEXTJS_CACHE_BUCKET_NAME`\n\nS3 bucket name for storing cached data (optimized images, data cache, full route cache, `'use cache: remote'`).\n\n#### `CDK_NEXTJS_REVALIDATION_TABLE_NAME`\n\nDynamoDB table name for tracking cache revalidations and tag-to-cache-key mappings.\n\n#### `DEBUG`\n\nNot set by default. Set it to `cdk-nextjs:*` to enable debug logs. This is especially useful to see cache handler activity.\n\n### `next.config.js` options cdk-nextjs reads\n\nBoth are read out of your build, so you set them in one place — your app — and the\ninfrastructure follows.\n\n#### `basePath`\n\nBecomes the S3 key prefix for static assets and the prefix on every CloudFront\ncache behavior. See [Resource Isolation](#resource-isolation); the `basePath`\nprop only exists to be explicit about it.\n\n#### `assetPrefix`\n\n- **A path** (`assetPrefix: \"/cdn\"`) — Next.js emits bundle URLs as\n `/cdn/_next/static/...`, on top of `basePath` rather than under it, while the\n objects stay in S3 under `<basePath>/_next/static/...`. `NextjsGlobalFunctions`\n and `NextjsGlobalContainers` add a cache behavior for\n `<assetPrefix>/_next/static*` pointing at the assets bucket, with a CloudFront\n Function that rewrites the prefix back to the S3 keys. It costs one of the 25\n cache behaviors cdk-nextjs budgets for you. **Not supported on\n `NextjsRegionalFunctions` or `NextjsRegionalContainers`** — nothing there maps\n the prefix back, so bundles would 404; synth warns if your app sets one.\n- **An absolute URL** (`assetPrefix: \"https://cdn.example.com\"`) — names an origin\n cdk-nextjs doesn't serve, so nothing is added, on any construct. Point that host\n at the assets bucket yourself, including the `basePath` prefix the objects are\n stored under.\n- **An absolute URL with a path** (`assetPrefix: \"https://cdn.example.com/cdn\"`) —\n its path is treated exactly like the path case above, because `next build`\n compiles a `/cdn/_next/:path+` rewrite of its own: `next start` serves bundles\n under that path too, so the Global constructs answer there as well. Useful when\n that host is a second domain on the same distribution.\n\n## Splitting a Large App Across Functions\n\nOnly for `NextjsGlobalFunctions` and `NextjsRegionalFunctions`, and only if you\nneed it. AWS Lambda caps a function's unzipped code at 250 MB. If your app\nexceeds it, cdk-nextjs fails at synth with the measured size and points you here:\n\n```\nFunction group \"default\" is 274 MB unzipped, over Lambda's 250 MB limit. Use the\n`functionGroups` prop to package routes into separate functions. Note that\nsplitting only removes route-local code — anything reachable from a shared layout\nor the `next` runtime is in every group.\n```\n\n`functionGroups` declares which routes get their own Lambda. Everything you do\nnot name stays on the `default` function:\n\n```ts\nnew NextjsGlobalFunctions(this, \"Nextjs\", {\n buildDirectory: join(import.meta.dirname, \"..\", \"web\"),\n functionGroups: [\n { name: \"reports\", routes: [\"/dashboard/reports/**\"] },\n { name: \"admin\", routes: [\"/admin\", \"/admin/**\", \"/settings\"] },\n ],\n});\n```\n\nEach group becomes one Lambda function containing only the routes it owns (plus\nthe framework closure every function needs), and one CloudFront behavior — or API\nGateway resource, for `NextjsRegionalFunctions` — per pattern.\n\n**Route patterns** are either an exact path (`/settings`) or a subtree\n(`/admin/**`). A subtree owns what is _under_ it, not the path itself:\n`/admin/**` does not claim `/admin`. To own a page and everything under it, list\nboth, as the example above does: `[\"/admin\", \"/admin/**\"]`. Where two groups\ncould both match, the longest pattern wins, so `/api/**` and `/api/reports/**`\ncan coexist in different groups. Dynamic segments (`/blog/[slug]`), route group\nsegments (`/(marketing)/about`), `/`, and `/**` are rejected at synth —\nCloudFront matches literal path prefixes and cannot express them. `/index` is\naccepted for an App Router `app/index/page.tsx`, but not for a Pages Router home\npage, which is the same file as `/`.\n\n**What is routed for you.** Patterns decide which _files_ a group packages; the\nedge then has to send every URL those files serve to that group. cdk-nextjs\nderives these without extra patterns:\n\n- A Pages Router page's data URL, `/_next/data/<buildId>/<page>.json`. The\n behavior carries the literal build ID, so it changes on every deploy; a\n client still on the previous build falls through to the `default` function,\n which answers 404, and the Next.js client reloads the page.\n- The `trailingSlash` form of an exact pattern (`/pricing/`). CloudFront gets a\n behavior for it; on `NextjsRegionalFunctions` none is needed, because API\n Gateway already routes `/pricing/` to the `/pricing` resource.\n- The parent of an optional catch-all. `/shop/**` moving\n `app/shop/[[...slug]]/page.tsx` also routes `/shop`, which the same file\n serves. Do not add `/shop` yourself: it matches no route and is rejected.\n- An [interception route](https://nextjs.org/docs/app/api-reference/file-conventions/intercepting-routes)\n is packaged with the group that owns the URL it intercepts, not by its own\n path: `app/feed/(..)photo/[id]` follows `/photo/[id]`, because a soft\n navigation requests `/photo/1` and Next.js rewrites it in whichever function\n receives it.\n\n**What synth rejects.** After assigning routes, cdk-nextjs replays the\nCloudFront behaviors over every URL each file serves and fails when one would\nreach a function without its file, naming the file, the URL and the pattern to\nadd. That covers:\n\n- A file behind several templates that a pattern only partly covers — root\n params (`app/[locale]/page.tsx` prerendered as `/en` and `/de`) grouped with\n `/en` alone. A dynamic first segment can never be routed, so such a file stays\n in `default`.\n- An intercepted URL space split between groups (`/photo/[id]` in one,\n `/photo/1` in another), since the intercepting file cannot be in both.\n- A `next.config` rewrite whose source reaches one group and whose destination\n file is in another: rewrites run inside the function that received the\n request. Only rewrites with a literal destination are checked.\n- A group pattern that duplicates a top-level `public/` entry's behavior\n (`public/docs/` and `/docs/**`), or sits under one (`/docs/guide/**`), which\n would send the group's routes to S3.\n\nNot checked, because it is only known at request time: **a middleware\n`NextResponse.rewrite()`** to a route in another group reaches the function that\nreceived the original URL, which lacks the route's file. It answers 404 (or a\n308 to the canonical URL when only the case differs) and logs a warning naming\nthe group that owns the route. Keep a middleware rewrite's source and\ndestination in the same group. The same goes\nfor a `next.config` rewrite whose destination is built from its parameters\n(`/b/:slug` → `/blog/:slug`), and for a dynamic segment of a `default` route\nthat overlaps a group's literal path (`/[section]/intro` against `/docs/**`).\nLikewise **a Pages Router `res.revalidate()`** renders the page in the function\nthat called it, so it can only revalidate pages in its own group; the error\nnames the group that owns the page. Use `revalidatePath()` or `revalidateTag()`\nacross groups. And **an `<Image>` whose `src` is a route in another group**\n(`/api/avatar/42` under an `/api/**` group) can't be optimized: `/_next/image`\nruns in the `default` function, which fetches a local source that isn't a\n`public/` or `_next/static` file by running its route in-process, and it doesn't\ncarry that route, so the image request fails. Keep image-serving routes in\n`default`, or point `src` at a `public/` file or a remote URL.\n\n**What splitting does and does not save.** Every function ships the same `next`\nruntime closure, so splitting only moves route-_local_ code and its dependencies.\nA group whose routes import a large library is worth extracting; splitting an app\nin half does not halve either function.\n\nNotes:\n\n- Group names must be valid CDK construct ids (letters, digits, `-`). `default`\n is reserved.\n- A pattern that matches no route in the build is a synth error, not a silent\n no-op — it is almost always a typo.\n- Cannot be combined with `i18n`: locale-prefixed routes would need one\n CloudFront behavior per locale per pattern.\n- Group patterns (and the routes derived from them above) count against the\n same CloudFront behavior budget as your `public/` entries (see\n [Limitations](#limitations)).\n- Per-group `overrides` let you size each function independently:\n `{ name: \"reports\", routes: [...], overrides: { functionProps: { memorySize: 2048 } } }`.\n\n## Architecture\n\nHow requests are served inside the compute — the adapter runtime, and where it deliberately differs from `next start` — is in [docs/adapter-runtime.md](./docs/adapter-runtime.md).\n\n### `NextjsGlobalFunctions`\n\nArchitecture includes [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html) Functions to respond to dynamic requests and [CloudFront](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Introduction.html) Distribution to globally serve requests and distribute static assets. Use this construct when you have unpredictable traffic, can afford occasional latency (i.e. cold starts - [typically 1% of production traffic](https://aws.amazon.com/blogs/compute/operating-lambda-performance-optimization-part-1/)), and/or want the most granular pricing model. ([code](./src/root-constructs/nextjs-global-functions.ts))\n\n```mermaid\narchitecture-beta\n group aws(cloud)[AWS Cloud]\n group cache[Cache Layer] in aws\n\n service user(internet)[User]\n service cloudfront(server)[CloudFront Distribution] in aws\n service s3static(disk)[S3 Static Assets] in aws\n service lambda(server)[Lambda Function] in aws\n service dynamodb(database)[DynamoDB Table] in cache\n service s3cache(disk)[S3 Cache Bucket] in cache\n\n user:R --> L:cloudfront\n cloudfront:R --> L:s3static\n cloudfront:R --> L:lambda\n lambda:R --> L:dynamodb\n lambda:R --> L:s3cache\n```\n\n### `NextjsGlobalContainers`\n\nArchitecture includes [ECS Fargate](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AWS_Fargate.html) containers to respond to dynamic requests and [CloudFront](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Introduction.html) Distribution to globally serve requests and distribute static assets. Use this option when you have predictable traffic, need the lowest latency, and/or can afford a less granular pricing model. ([code](./src/root-constructs/nextjs-global-containers.ts))\n\n```mermaid\narchitecture-beta\n group aws(cloud)[AWS Cloud]\n group vpc[VPC] in aws\n group cache[Cache Layer] in aws\n\n service user(internet)[User]\n service cloudfront(server)[CloudFront Distribution] in aws\n service s3static(disk)[S3 Static Assets] in aws\n service alb(server)[Application Load Balancer] in vpc\n service fargate(server)[ECS Fargate Containers] in vpc\n service dynamodb(database)[DynamoDB Table] in cache\n service s3cache(disk)[S3 Cache Bucket] in cache\n\n user:R --> L:cloudfront\n cloudfront:R --> L:s3static\n cloudfront:R --> L:alb\n alb:R --> L:fargate\n fargate:R --> L:dynamodb\n fargate:R --> L:s3cache\n```\n\n### `NextjsRegionalContainers`\n\nArchitecture includes [ECS Fargate](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AWS_Fargate.html) containers to respond to dynamic requests and [Application Load Balancer](https://aws.amazon.com/elasticloadbalancing/application-load-balancer/) to regionally serve requests. Use this options when you cannot use Amazon CloudFront (i.e. [AWS GovCloud](https://aws.amazon.com/govcloud-us/?whats-new.sort-by=item.additionalFields.postDateTime&whats-new.sort-order=desc)). ([code](./src/root-constructs/nextjs-regional-containers.ts#L41))\n\n```mermaid\narchitecture-beta\n group aws(cloud)[AWS Cloud]\n group vpc[VPC] in aws\n group cache[Cache Layer] in aws\n\n service user(internet)[User]\n service alb(server)[Application Load Balancer] in vpc\n service fargate(server)[ECS Fargate Containers] in vpc\n service dynamodb(database)[DynamoDB Table] in cache\n service s3cache(disk)[S3 Cache Bucket] in cache\n\n user:R --> L:alb\n alb:R --> L:fargate\n fargate:R --> L:dynamodb\n fargate:R --> L:s3cache\n```\n\n### `NextjsRegionalFunctions`\n\nArchitecture includes [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html) Functions to respond to dynamic requests and [API Gateway REST API](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-rest-api.html) to regionally serve requests and distribute static assets. Use this options when you cannot use Amazon CloudFront (i.e. [AWS GovCloud](https://aws.amazon.com/govcloud-us/?whats-new.sort-by=item.additionalFields.postDateTime&whats-new.sort-order=desc)). ([code](./src/root-constructs/nextjs-regional-functions.ts))\n\n```mermaid\narchitecture-beta\n group aws(cloud)[AWS Cloud]\n group cache[Cache Layer] in aws\n\n service user(internet)[User]\n service apigateway(server)[API Gateway REST API] in aws\n service s3static(disk)[S3 Static Assets] in aws\n service lambda(server)[Lambda Function] in aws\n service dynamodb(database)[DynamoDB Table] in cache\n service s3cache(disk)[S3 Cache Bucket] in cache\n\n user:R --> L:apigateway\n apigateway:R --> L:s3static\n apigateway:R --> L:lambda\n lambda:R --> L:dynamodb\n lambda:R --> L:s3cache\n```\n\n## Why\n\nThe simplest path to deploy Next.js is on [Vercel](https://vercel.com/) - the Platform-as-a-Service company behind Next.js. However, deploying to Vercel can be expensive and some developers want all of their workloads running _directly_ on AWS. Developers can deploy Next.js on AWS through [AWS Amplify Hosting](https://docs.aws.amazon.com/amplify/latest/userguide/ssr-Amplifysupport.html), but Amplify does not support all Next.js features and manages AWS resources for you so they cannot be customized. If Amplify meets your requirements we recommend you use it, but if you want to use all Next.js features or want more visibility into the AWS resources then this construct is for you.\n\n## Design Principles\n\n- Integrate through Next.js's official interfaces. Build on the [Deployment Adapter](https://nextjs.org/docs/app/guides/deployment-adapters) API and [`@next/routing`](https://www.npmjs.com/package/@next/routing) rather than Next.js internals, so new Next.js versions rarely break this construct. Where no public interface exists yet, the dependency is listed in [Next.js private APIs](docs/nextjs-private-apis.md).\n- Security first.\n- One architecture does not fit all.\n- Enable customization everywhere.\n\n## Bring Your Own Resources\n\ncdk-nextjs supports importing existing AWS resources instead of creating new ones. This is especially useful for per-branch (MR/PR) environments where you deploy shared infrastructure (VPC, ECS cluster, ALB) once and spin up lightweight branch stacks that reuse it.\n\n### Supported Resources\n\n| Resource | Prop | Available On |\n| --------------------------- | -------------------- | ---------------------------------------------------- |\n| S3 Cache Bucket | `cacheBucket` | All constructs |\n| DynamoDB Revalidation Table | `revalidationTable` | All constructs |\n| S3 Static Assets Bucket | `staticAssetsBucket` | All constructs |\n| CloudFront Distribution | `distribution` | `NextjsGlobalFunctions`, `NextjsGlobalContainers` |\n| ECS Cluster | `ecsCluster` | `NextjsGlobalContainers`, `NextjsRegionalContainers` |\n| ALB | `alb` | `NextjsGlobalContainers`, `NextjsRegionalContainers` |\n\n### Resource Isolation\n\n- **Cache bucket and DynamoDB table** must be dedicated to one deployment. Sharing either between deployments (branches, stages, apps) is not supported: each deploy's post-deploy step prunes every cache object and revalidation entry that isn't from its own current build, so deploying one branch wipes the others' caches. Buckets and tables are cheap, so give each deployment its own, or leave `cacheBucket`/`revalidationTable` unset and let cdk-nextjs create them (they are removed with the stack).\n- **Static assets bucket** can be shared, but only between deployments with different `basePath`s, which become their S3 key prefixes. Pruning only looks at `<basePath>/_next/`, so it never touches another prefix. Two deployments under the same prefix (for example two subdomain previews both at the root) overwrite each other's `public/` files and prune each other's `_next/` assets once they are past the prune TTL (30 days by default), so give those their own buckets. `NextjsGlobalFunctions` and `NextjsGlobalContainers` read the `basePath` out of your Next.js build and use it as the S3 key prefix, since CloudFront serves assets from S3 by request path and the two can't differ. Set the `basePath` prop only if you want to be explicit about it; a value that disagrees with your app's fails at synth. Each deployment also adds an ownership tag per static asset upload (1 to 3, by whether the build has `public/` files and service workers) to a bucket created in your CDK app; an imported bucket gets none. S3 allows 50 tags per bucket, so such a bucket holds at least 16 deployments.\n\n### Shared ALB and `removeAutoCreatedListener()`\n\n`ApplicationLoadBalancedFargateService` always creates a listener on port 80 — there is no opt-out. When you import an ALB that already has a listener on that port, the duplicate causes a deployment failure. Since CDK doesn't expose a way to prevent this, `removeAutoCreatedListener()` surgically removes the generated CloudFormation resources: the `CfnListener`, its security group ingress rule, rebuilds the ECS service `DependsOn` without the deleted listener, and removes auto-created `CfnOutput` resources:\n\n```ts\nconst nextjs = new NextjsRegionalContainers(this, \"Nextjs\", {\n // ...\n alb: sharedAlb,\n ecsCluster: sharedCluster,\n});\nnextjs.nextjsContainers.removeAutoCreatedListener();\n```\n\n### Examples\n\nSee [examples/bring-your-own/](./examples/bring-your-own/) for a complete deployable example with a shared VPC, ECS cluster, and ALB, per-branch host-header routing, and a cache bucket, revalidation table, and static assets bucket per branch.\n\n## Preview Environments (Per-Branch Deployments)\n\ncdk-nextjs can deploy ephemeral preview environments per merge request (MR) or pull request (PR). The recommended approach uses subdomain-based routing (`pr-123.app.example.com`) so each preview environment runs the same Next.js build as production — no `basePath` configuration or separate builds required.\n\nSee [examples/bring-your-own/](./examples/bring-your-own/) for a fully deployable example using `NextjsRegionalContainers` with a shared VPC, ALB, and ECS Cluster (connected via SSM Parameter Store), and S3 buckets and a DynamoDB table owned by each branch stack.\n\nEach preview environment needs its own cache bucket and revalidation table (see [Resource Isolation](#resource-isolation)). Since every preview serves the same build at the root, give each its own static assets bucket too. Leaving `cacheBucket`, `revalidationTable`, and `staticAssetsBucket` unset does this: cdk-nextjs creates them in the branch stack and deletes them when it's torn down.\n\n### Prerequisites\n\n- Wildcard DNS record: `*.app.example.com` → your routing layer (ALB, CloudFront, API Gateway)\n- Wildcard ACM certificate: `*.app.example.com`\n\n### Per-Architecture Recommendations\n\n#### `NextjsGlobalContainers` and `NextjsRegionalContainers` (ALB-based)\n\nSubdomain routing via ALB host-based listener rules. This is the fastest and simplest approach. For `NextjsGlobalContainers`, CloudFront forwards the `Host` header to the ALB origin, so the ALB handles all branch routing — no CloudFront changes needed per branch.\n\nSee [examples/bring-your-own/](./examples/bring-your-own/) for the full implementation.\n\n#### `NextjsRegionalFunctions` (API Gateway)\n\nSubdomain routing via API Gateway custom domain mappings.\n\n1. Per branch, deploy a cdk-nextjs stack that creates its own API Gateway, Lambda function, S3 buckets, and DynamoDB table\n2. Create an API Gateway custom domain (`pr-123.app.example.com`) mapped to the branch's API stage\n3. Tear down the branch stack on MR close\n\n#### `NextjsGlobalFunctions` (Lambda + CloudFront)\n\nRequires a separate cdk-nextjs stack per branch, each with its own CloudFront distribution. CloudFront cannot route to different Lambda Function URL origins based on the `Host` header — origin selection is determined by cache behavior path patterns, not request headers.\n\n1. Per branch, deploy a full cdk-nextjs stack that creates its own CloudFront distribution, Lambda function, S3 buckets, and DynamoDB table\n2. Point `pr-123.app.example.com` DNS to the branch's CloudFront distribution\n3. Tear down the branch stack on MR close\n\nNote: CloudFront distributions take several minutes to create/update, so this architecture has the slowest preview environment spin-up time.\n\n## Limitations\n\n- If using `NextjsGlobalFunctions` or `NextjsGlobalContainers` (which use CloudFront), each top level file/directory in `public/` takes a CloudFront cache behavior, and a distribution's default quota is 75 behaviors (cdk-nextjs uses 3 to 6 itself). We recommend you put all of your public assets into one top level directory (i.e. public/static) so you don't reach this limit. If you raise the quota for your account, set `maxCacheBehaviors` on the distribution props (`overrides.nextjsGlobalFunctions.nextjsDistributionProps`, or the Containers equivalent) to match. The synth check only counts the behaviors cdk-nextjs adds, so if you pass your own `distribution` (or add behaviors through `overrides.nextjsDistribution.distributionProps`), lower `maxCacheBehaviors` by the behaviors it already has. See [CloudFront Quotas](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-limits.html) for more information.\n- If using `NextjsGlobalFunctions` or `NextjsGlobalContainers`, on-demand revalidation ([revalidatePath](https://nextjs.org/docs/app/api-reference/functions/revalidatePath), [revalidateTag](https://nextjs.org/docs/app/api-reference/functions/revalidateTag)) creates the CloudFront invalidations for you (so does the Pages Router's `res.revalidate()`, for the page's HTML and `_next/data` copies), but [invalidations](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Invalidation.html) are eventually consistent: until one completes (usually seconds, occasionally minutes), some edge locations can still serve the previous copy.\n - **Burst limit.** CloudFront allows 15 wildcard invalidation paths in progress per distribution, and each page cdk-nextjs invalidates is one wildcard path (`/blog*`). Next.js sends every `revalidatePath`/`revalidateTag` from one request as a single call, one invalidation per cache-life profile, however many pages it covers. A Pages Router `res.revalidate()` sends one invalidation per call, and a page regenerated after a stale-while-revalidate `revalidateTag(tag, profile)` sends one more when it lands. When the quota is full, cdk-nextjs retries the request as a single `/*` (a colder edge, never a stale page). If that is also rejected, it logs `Failed to create CloudFront invalidation` and the page stays stale at the edge until its `s-maxage` expires.\n - **For bulk updates** (a CMS webhook touching many pages), call `revalidateTag` with a tag the pages share, or `revalidatePath` for each page within one request, rather than looping `res.revalidate()`. If you need to know when invalidations are dropped, add a CloudWatch Logs metric filter on that log line.\n- If using `NextjsGlobalFunctions`, a client-supplied `Authorization` header does not reach your app: CloudFront signs each request to the Lambda Function URL with SigV4, which uses that header. Send credentials under a different name (e.g. `x-authorization`) and read that header in your app. cdk-nextjs does not rename it for you — it no longer uses [AWS Lambda Web Adapter](https://github.com/awslabs/aws-lambda-web-adapter), so `AWS_LWA_AUTHORIZATION_SOURCE` no longer applies.\n- If using `NextjsGlobalFunctions`, a `POST` or `PUT` with a request body must carry an `x-amz-content-sha256` header holding the hex SHA-256 of that body. This is [AWS behavior](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-lambda.html), not a cdk-nextjs choice: CloudFront signs the origin request to the Lambda Function URL with SigV4 but does not hash the body, and Lambda rejects an unsigned payload with `403 InvalidSignatureException`. Requests from your own pages are handled for you — cdk-nextjs injects a `fetch`/`XMLHttpRequest` wrapper into the client bundle that adds the header, so server actions, route handlers, `fetch` and `XMLHttpRequest` from the browser work untouched, whatever the body type. The exception is a native `<form method=\"post\">` submitted before the page hydrates (a server action form without JavaScript, or clicked before the bundle loads): the browser sends it, not the wrapper, so it has no header and gets the 403. **Anything that is not that browser bundle has to add the header itself**: `curl`, a mobile app, a webhook provider, another service calling your API routes. Server-to-server callers can compute it with the AWS SDK's `Sha256`, or with `crypto.createHash(\"sha256\").update(body).digest(\"hex\")`. The other three deployment types are unaffected.\n- If using `NextjsGlobalFunctions`, a `HEAD` request is answered with `content-length: 0`, whatever length your handler declares. This is Lambda Function URL behavior: the same runtime's declared length reaches the client through API Gateway (`NextjsRegionalFunctions`) and from an ALB, with or without CloudFront in front (the two Containers types).\n- Group patterns declared via [`functionGroups`](#splitting-a-large-app-across-functions) also count against the CloudFront behavior limit above.\n- If using `NextjsRegionalFunctions` without a custom domain, API Gateway REST APIs require a [stage name](https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-stages.html) (default: `/prod`) to be specified. This causes links to pages and static assets to break because they're not prefixed with the stage name. You can work around this issue by specifying [basePath](https://nextjs.org/docs/app/api-reference/config/next-config-js/basePath) in next.config.js as your stage name — leave the construct's `basePath` prop unset when you do, since API Gateway strips the stage before matching resources. API Gateway strips the stage from the path it passes to Lambda; cdk-nextjs puts it back for an app whose `basePath` starts with it, reading the stage off each request, so no middleware is needed and a renamed stage needs no configuration. Mapping a custom domain at the root avoids all of this — see [examples/regional-functions/README.md](./examples/regional-functions/README.md#with-a-custom-domain-no-stage-workarounds).\n\n## Additional Security Recommendations\n\nThis construct by default implements all AWS security best practices that a CDK construct library reasonably can considering cost and complexity. Below are additional security practices we recommend you implement within your CDK app. Please see them below:\n\n- [VPC Flow Logs](https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html). See [examples/](./examples) for sample implementation.\n- [Scan ECR Images For Vulnerabilities](https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-scanning.html).\n- For `NextjsGlobalFunctions` and `NextjsGlobalContainers`, [CloudFront Access Logs](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html). See [examples/](./examples) for sample implementation.\n- For `NextjsGlobalContainers` and `NextjsRegionalContainers`, use [ALB HTTPS Listener](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html)\n- If using `NextjsGlobalContainers` and `NextjsRegionalContainers`, enable `ReadonlyRootFilesystem`. This will remove ability to use Static On-Demand feature of Next.js so it's not enabled by default, but is recommended for security.\n\n## Estimated Costs\n\n### Assumptions\n\nThe following basic assumptions were used for a typical medium Next.js app. See [docs/usage.xlsx](./docs/usage.xlsx) for detailed assumptions and usage per construct type that you can plug into AWS Pricing Calculator.\n\n| Metric | Value |\n| ------------------------------------------------------------ | ----- |\n| Monthly Active Users | 1K |\n| Pages Visited Per Month Per User | 100 |\n| Avg Request Size | 50KB |\n| Static Requests Per Page (js, css, etc) | 15 |\n| Static Requests Cache Hit % | 50% |\n| Static Assets Size | 10GB |\n| Dynamic Requests Per Page (document, optimized images, etc.) | 5 |\n| Dynamic Cache Read % | 50% |\n| Dynamic Cache Write % | 5% |\n| Dynamic Cache Data Size | 10GB |\n| Average Dynamic Cache Request Size | 100KB |\n| Dynamic Revalidate Tag % | 1% |\n\nMore Details:\n\n- Assume ARM architecture for compute\n- AWS Region: us-east-1\n- Excludes charges related to: CloudWatch Logs, NAT Gateway data processing\n\n### NextjsGlobalFunctions\n\n[AWS Pricing Calculator](https://calculator.aws/#/estimate?id=23611f6fea87ef05d5fe87c33135ddde43b17a98)\n\n| Service | Monthly Usage | Estimated Monthly Cost (USD) |\n| ---------- | ---------------------------------------------- | ---------------------------- |\n| Lambda | 500K requests, 2 GB memory, 150ms avg duration | $0.00 (Always Free Tier) |\n| CloudFront | 2M requests, 100 GB transfer to internet | $0.00 (Always Free Tier) |\n| S3 | 20 GB storage, 1M GET, 250K PUT requests | $2.11 |\n| DynamoDB | 10 GB storage, 5K Reads, 5K Writes | $2.50 |\n| Total | | $8.09 |\n\n### NextjsGlobalContainers\n\n[AWS Pricing Calculator](https://calculator.aws/#/estimate?id=02f0073e612d1eee2a7ccace2c636adc5f0acab7)\n\n| Service | Monthly Usage | Estimated Monthly Cost (USD) |\n| ----------- | ---------------------------------------- | ---------------------------- |\n| ECS Fargate | 1 task (1 vCPU, 2 GB) | $28.44 |\n| ALB | 1 LB, 1.04GB/hr, 5.79 conn/sec | $22.50 |\n| CloudFront | 2M requests, 100 GB transfer to internet | $0.00 (Always Free Tier) |\n| S3 | 20 GB storage, 1M GET, 250K PUT requests | $2.11 |\n| DynamoDB | 10 GB storage, 5K Reads, 5K Writes | $2.50 |\n| VPC | NAT Gateway, 2 AZs | $65.70 |\n| Total | | $121.25 |\n\n### NextjsRegionalContainers\n\n[AWS Pricing Calculator](https://calculator.aws/#/estimate?id=e214abe60eb4e24fc5866d07ef4355393261af3c)\n\n| Service | Monthly Usage | Estimated Monthly Cost (USD) |\n| ----------- | ------------------------------------------ | ---------------------------- |\n| ECS Fargate | 1 task (2 vCPU, 4 GB), always on | $28.44 |\n| ALB | 1 LB, 4.17 GB/hr, 23.15 conn/sec | $40.78 |\n| S3 | 10 GB storage, 250K GET, 250K PUT requests | $1.58 |\n| DynamoDB | 10 GB storage, 5K Reads, 5K Writes | $2.50 |\n| VPC | NAT Gateway, 2 AZs | $65.70 |\n| Total | | $139.00 |\n\n### NextjsRegionalFunctions\n\n[AWS Pricing Calculator](https://calculator.aws/#/estimate?id=60da38c7993c1baeee2fee4bd19ba6441608bb15)\n\n| Service | Monthly Usage | Estimated Monthly Cost (USD) |\n| ----------- | ---------------------------------------------- | ---------------------------- |\n| Lambda | 500K requests, 2 GB memory, 150ms avg duration | $0.00 (Always Free Tier) |\n| API Gateway | 2M requests | $7.00 |\n| S3 | 10 GB storage, 250K GET, 250K PUT requests | $1.58 |\n| DynamoDB | 10 GB storage, 5K Reads, 5K Writes | $2.50 |\n| Total | | $11.08 |\n\n## Performance\n\nMeasured with [k6](https://grafana.com/docs/k6/latest/) from EC2 in us-east-1, the region of the stacks under test (one load generator per stack), against a small benchmark app ([`examples/bench-app`](./examples/bench-app)) that makes no calls outside its own stack. Functions run the default 2048 MB Lambda functions. Containers run the default 1 vCPU / 2 GB Fargate tasks, with CPU autoscaling from 2 to 10 tasks added (the default is one task and no autoscaling). Methodology, caveats, and how to reproduce the numbers: [`examples/load-tests`](./examples/load-tests).\n\nWhat each route measures:\n\n- `static-asset`, `static`, `image`: CloudFront's cache on the Global constructs, and the construct itself on the Regional ones.\n- `isr`: the cache until the page is stale (10 s), then a background revalidation through the S3 + DynamoDB cache.\n- `ssr`, `stream`, `rsc`, `api`: the construct's compute on every request, on every construct.\n\n<!-- tables generated by `pnpm report` in examples/load-tests -->\n\n| Construct | `ssr` at 10 req/s | `ssr` at 50 req/s | `ssr` capacity | `isr` capacity | Cold start p50 |\n| -------------------------- | ----------------- | ----------------------------------------- | -------------- | -------------- | -------------- |\n| `NextjsGlobalFunctions` | 36 / 103 | 33 / 84 | ≥ 6560 req/s | ≥ 6560 req/s | 1390 ms |\n| `NextjsGlobalContainers` | 19 / 44 | 18 / 219 | 194 req/s | ≥ 6400 req/s | – |\n| `NextjsRegionalContainers` | 22 / 172 | 1972 / 39536 ⚠️ 0.54% errors, 76% dropped | 675 req/s | ≥ 6075 req/s | – |\n| `NextjsRegionalFunctions` | 32 / 114 | 30 / 103 | ≥ 6560 req/s | ≥ 6560 req/s | 1380 ms |\n\n_Latency is p50 / p99 in ms, with every route loaded at that rate at once. Capacity is the highest rate sustained with p99 under 1000 ms and under 1% errors._\n\nWhat this means for choosing one:\n\n- **Functions constructs scale with no sizing.** Both held at least 6,560 req/s of SSR, the load generator's limit, at the same latency as at 10 req/s. The cost is a cold start of about 1.4 s on a new execution environment.\n- **Containers constructs are fastest per request but need sizing.** Two 1 vCPU tasks served SSR at 19–22 ms p50 against Lambda's ~30 ms, but tasks take minutes to add. Past capacity they don't degrade gradually: tasks too busy to answer the ALB health check are replaced, which leaves fewer tasks for the same load. Leave headroom.\n- **CloudFront carries the Global constructs' cached traffic.** Prerendered pages, ISR hits, images and assets were answered at the edge in 2–3 ms at every rate. On the Regional constructs every request reaches the construct: `NextjsRegionalContainers` serves assets and image optimization from the same tasks, so 50 req/s on every route at once (400 req/s) is already more than two tasks handle.\n- **Cached pages scale on every construct.** ISR hits held at least 6,000 req/s on all four: at the edge on the Global constructs, and through the S3 + DynamoDB cache on the Regional ones, where each instance holds a tag's revalidation marker for a second (`CDK_NEXTJS_TAG_REFRESH_MS`, see the [Caching Guide](./docs/caching-guide.md)).\n\n<details>\n<summary><code>NextjsGlobalFunctions</code></summary>\n\nLatency per route, p50 / p99 in ms, with every route at the same rate at once:\n\n| Route | 10 req/s | 50 req/s | 250 req/s | 1000 req/s | CDN hits |\n| ------------- | --------- | --------- | --------- | ---------- | -------- |\n| static-asset | 2.1 / 4.8 | 2.1 / 4.7 | 2.0 / 4.9 | 2.1 / 11 | 100% |\n| static | 3.3 / 7.5 | 3.2 / 6.8 | 3.1 / 7.3 | 3.2 / 13 | 100% |\n| isr | 3.3 / 7.4 | 3.3 / 7.7 | 3.2 / 7.2 | 3.2 / 12 | 100% |\n| ssr | 36 / 103 | 33 / 84 | 31 / 86 | 29 / 73 | 0% |\n| stream | 233 / 268 | 230 / 261 | 228 / 259 | 226 / 252 | 0% |\n| stream (TTFB) | 32 / 89 | 29 / 66 | 27 / 65 | 25 / 57 | |\n| rsc | 32 / 67 | 28 / 61 | 27 / 60 | 25 / 52 | 0% |\n| api | 29 / 79 | 26 / 55 | 24 / 61 | 23 / 47 | 0% |\n| image | 3.2 / 6.3 | 3.1 / 6.8 | 3.1 / 7.0 | 3.1 / 12 | 100% |\n\nCapacity: `isr` ≥ 6560 req/s, `ssr` ≥ 6560 req/s.\n\nCold start, time to first byte of `/ssr` on a new execution environment: p50 1390 ms, p90 1451 ms (warm: 84 ms).\n\nBrowser, p75 in ms, under 50 req/s per route:\n\n| Route | LCP | TTFB | Client-side navigation |\n| ------ | --- | ---- | ---------------------- |\n| static | 76 | 13 | 15 |\n| ssr | 80 | 39 | 53 |\n| isr | 52 | 8.7 | 12 |\n| stream | 64 | 34 | 38 |\n| image | 52 | 6.7 | 10 |\n\n</details>\n\n<details>\n<summary><code>NextjsGlobalContainers</code></summary>\n\nLatency per route, p50 / p99 in ms, with every route at the same rate at once:\n\n| Route | 10 req/s | 50 req/s | CDN hits |\n| ------------- | --------- | --------- | -------- |\n| static-asset | 1.4 / 3.9 | 1.5 / 3.7 | 100% |\n| static | 1.9 / 4.8 | 1.8 / 3.7 | 100% |\n| isr | 2.0 / 4.4 | 1.7 / 4.0 | 100% |\n| ssr | 19 / 44 | 18 / 219 | 0% |\n| stream | 217 / 242 | 217 / 359 | 0% |\n| stream (TTFB) | 17 / 45 | 16 / 207 | |\n| rsc | 12 / 26 | 12 / 86 | 0% |\n| api | 11 / 23 | 10 / 81 | 0% |\n| image | 2.0 / 4.7 | 1.7 / 4.1 | 100% |\n\nCapacity: `isr` ≥ 6400 req/s, `ssr` 194 req/s.\n\nBrowser, p75 in ms, under 50 req/s per route:\n\n| Route | LCP | TTFB | Client-side navigation |\n| ------ | --- | ---- | ---------------------- |\n| static | 88 | 12 | 17 |\n| ssr | 80 | 26 | 39 |\n| isr | 56 | 6.1 | 13 |\n| stream | 64 | 20 | 25 |\n| image | 52 | 5.4 | 11 |\n\n</details>\n\n<details>\n<summary><code>NextjsRegionalContainers</code></summary>\n\nLatency per route, p50 / p99 in ms, with every route at the same rate at once:\n\n| Route | 10 req/s | 50 req/s | CDN hits |\n| ------------- | --------- | ----------------------------------------- | -------- |\n| static-asset | 18 / 159 | 1698 / 28824 ⚠️ 0.40% errors, 72% dropped | no CDN |\n| static | 41 / 163 | 916 / 28298 ⚠️ 0.46% errors, 66% dropped | no CDN |\n| isr | 40 / 169 | 697 / 27146 ⚠️ 0.36% errors, 57% dropped | no CDN |\n| ssr | 22 / 172 | 1972 / 39536 ⚠️ 0.54% errors, 76% dropped | no CDN |\n| stream | 221 / 354 | 1909 / 27423 ⚠️ 0.44% errors, 72% dropped | no CDN |\n| stream (TTFB) | 19 / 166 | 1881 / 27162 | |\n| rsc | 9.4 / 64 | 433 / 26066 ⚠️ 0.25% errors, 39% dropped | no CDN |\n| api | 6.9 / 55 | 429 / 26041 ⚠️ 0.25% errors, 38% dropped | no CDN |\n| image | 140 / 440 | 1599 / 27489 ⚠️ 0.22% errors, 69% dropped | no CDN |\n\nCapacity: `isr` ≥ 6075 req/s, `ssr` 675 req/s.\n\nBrowser, p75 in ms, under 10 req/s per route. `static` is each visit's first page: on a plain-HTTP origin, Chrome tries HTTPS first and falls back after about 3 s (HTTPS-Upgrades), which real visitors pay too. Put a certificate on the ALB to avoid it.\n\n| Route | LCP | TTFB | Client-side navigation |\n| ------ | ---- | ---- | ---------------------- |\n| static | 3100 | 3047 | 16 |\n| ssr | 68 | 14 | 27 |\n| isr | 88 | 43 | 13 |\n| stream | 48 | 11 | 13 |\n| image | 212 | 38 | 9.6 |\n\n</details>\n\n<details>\n<summary><code>NextjsRegionalFunctions</code></summary>\n\nLatency per route, p50 / p99 in ms, with every route at the same rate at once:\n\n| Route | 10 req/s | 50 req/s | 250 req/s | 1000 req/s | CDN hits |\n| ------------- | --------- | --------- | --------- | ---------- | -------- |\n| static-asset | 34 / 76 | 32 / 72 | 30 / 72 | 30 / 68 | no CDN |\n| static | 58 / 138 | 57 / 140 | 57 / 147 | 57 / 127 | no CDN |\n| isr | 58 / 149 | 56 / 124 | 56 / 145 | 55 / 125 | no CDN |\n| ssr | 32 / 114 | 30 / 103 | 29 / 115 | 29 / 98 | no CDN |\n| stream | 229 / 293 | 227 / 288 | 227 / 299 | 226 / 282 | no CDN |\n| stream (TTFB) | 27 / 85 | 25 / 84 | 25 / 97 | 24 / 76 | |\n| rsc | 27 / 76 | 26 / 73 | 25 / 83 | 25 / 70 | no CDN |\n| api | 24 / 84 | 22 / 70 | 22 / 97 | 22 / 67 | no CDN |\n| image | 127 / 210 | 125 / 221 | 125 / 236 | 123 / 211 | no CDN |\n\nCapacity: `isr` ≥ 6560 req/s, `ssr` ≥ 6560 req/s.\n\nCold start, time to first byte of `/ssr` on a new execution environment: p50 1380 ms, p90 1442 ms (warm: 71 ms).\n\nBrowser, p75 in ms, under 50 req/s per route:\n\n| Route | LCP | TTFB | Client-side navigation |\n| ------ | --- | ---- | ---------------------- |\n| static | 128 | 70 | 17 |\n| ssr | 88 | 35 | 50 |\n| isr | 108 | 62 | 13 |\n| stream | 64 | 31 | 36 |\n| image | 220 | 60 | 9.6 |\n\n</details>\n\n## Guides\n\n- [Caching Guide](./docs/caching-guide.md)\n- [Pruning Guide](./docs/pruning-guide.md)\n- [Native Dependencies Guide](./docs/native-dependencies-guide.md)\n- [Next Build Output Guide](./docs/next-build-output-guide.ts)\n- [Development Guide](./docs/development-guide.ts)\n\n## Contributing\n\nSteps to build locally:\n\n1. `git clone https://github.com/cdklabs/cdk-nextjs.git`\n2. `cd cdk-nextjs`\n3. `pnpm i && pnpm compile && pnpm build`\n\nThis project uses Projen, so make sure to not edit [Projen](https://projen.io/) created files and only edit .projenrc.ts.\n\n## FAQ\n\nQ: How does this compare to [cdk-nextjs-standalone](https://github.com/jetbridge/cdk-nextjs) or [OpenNext](https://opennext.js.org)?<br/>\nA: cdk-nextjs builds on Next.js's official [Deployment Adapter](https://nextjs.org/docs/app/guides/deployment-adapters) API and runs requests through [`@next/routing`](https://www.npmjs.com/package/@next/routing), the routing library Next.js publishes for platform adapters. Next.js tells cdk-nextjs what it built, and routing follows the same rules as `next start`. Nothing re-implements Next.js's router or patches its server. The few Next.js internals cdk-nextjs does load (the image optimizer and static file server) are loaded as they are, not modified. This keeps upgrades cheap and breaking changes rare. cdk-nextjs is tested against Next.js's own end-to-end test suite; [harness-coverage.md](docs/harness-coverage.md) lists the cases that differ and why.\n\nQ: Why does cdk-nextjs depend upon Next.js v16.3 or higher?\nA: cdk-nextjs builds through the public [Adapter API](https://nextjs.org/docs/app/api-reference/config/next-config-js/adapterPath), and 16.3 is the first version whose build output carries everything it reads (middleware matchers and per-file asset hashes). 16.2 also added the [Image Optimization Caching](https://nextjs.org/docs/app/api-reference/config/next-config-js/incrementalCacheHandlerPath#image-optimization-caching) it relies on. The runtime bundles `@next/routing` at the version it was tested against (see `package.json`), and newer Next.js 16 releases are expected to work.\n\nQ: How does cdk-nextjs support caching in Next.js?<br/>\nA: See [Caching Guide](./docs/caching-guide.md)\n\nQ: How customizable is the `cdk-nextjs` package for different use cases?<br/>\nA: The `cdk-nextjs` package offers deep customization through _prop-based_ overrides. These can be accessed in the construct props, allowing you to override settings like VPC configurations, CloudFront distribution, and ECS/Fargate setup. For example, you can modify `nextjsBuildProps` to customize the build process or use `nextjsDistributionProps` to adjust how CloudFront handles caching and routing. This level of control makes it easy to adapt the infrastructure to your application’s specific performance, networking, or deployment needs.\n\nQ: How can I use a custom domain with `cdk-nextjs`?<br/>\nA: See [low-cost example](./examples/low-cost/app.ts).\n\nQ: What is difference between `NextjsGlobalFunctionsProps.overrides.nextjsDistribution` and `NextjsGlobalFunctionsProps.overrides.nextjsGlobalFunctions.nextjsDistributionProps`<br/>\nA: `NextjsGlobalFunctionsProps.overrides.nextjsDistribution` allows you to customize any construct's props _within_ `NextjsDistribution` and is likely what you want whereas `NextjsGlobalFunctionsProps.overrides.nextjsGlobalFunctions.nextjsDistributionProps` allows you to customize the props passed into the construct: `NextjsDistribution`. This principle also applies to other similarly named overrides.\n\nQ: How can I `cdk bootstrap --cloudformation-execution-policies ...` my AWS Account with limited permissions for cdk-nextjs to deploy?<br />\nA: See [docs/cdk-nextjs-cfn-exec-policy.json](./docs/cdk-nextjs-cfn-exec-policy.json). Note, this IAM Policy is scoped to all cdk-nextjs constructs so you can remove services if you know the construct you're using doesn't use that service.\n\n## Acknowledgements\n\nThis construct was built on the shoulders of giants. Thank you to the contributors of [cdk-nextjs-standalone](https://github.com/jetbridge/cdk-nextjs) and [OpenNext](https://opennext.js.org).\n\n## 🥂 Thanks Contributors\n\nThank you for helping other developers deploy Next.js apps on AWS\n\n<a href=\"https://github.com/cdklabs/cdk-nextjs/graphs/contributors\">\n <img src=\"https://contrib.rocks/image?repo=cdklabs/cdk-nextjs\" />\n</a>\n"
|
|
9035
|
+
"markdown": "\n[](https://www.npmjs.org/package/cdk-nextjs)\n\n\n# CDK Next.js Construct Library\n\n<!--BEGIN STABILITY BANNER-->\n\n---\n\n\n\n> The APIs of higher level constructs in this module are experimental and under active development.\n> They are subject to non-backward compatible changes or removal in any future version. These are\n> not subject to the [Semantic Versioning](https://semver.org/) model and breaking changes will be\n> announced in the release notes. This means that while you may use them, you may need to update\n> your source code when upgrading to a newer version of this package.\n\n---\n\n<!--END STABILITY BANNER-->\n\nDeploy [Next.js](https://nextjs.org/) apps on [AWS](https://aws.amazon.com/) with the [AWS CDK](https://aws.amazon.com/cdk/).\n\n## Features\n\n- Supports all features of Next.js App and Pages Router for [Node.js Runtime](https://nextjs.org/docs/app/building-your-application/rendering/edge-and-nodejs-runtimes#nodejs-runtime).\n- Choose your AWS architecture for Next.js with the supported constructs: `NextjsGlobalFunctions`, `NextjsGlobalContainers`, `NextjsRegionalContainers`, `NextjsRegionalFunctions`.\n- Global Content Delivery Network (CDN) built with [Amazon CloudFront](https://aws.amazon.com/cloudfront/) to deliver content with low latency and high transfer speeds.\n- Serverless functions powered by [AWS Lambda](https://aws.amazon.com/lambda/) or serverless containers powered by [AWS Fargate](https://aws.amazon.com/fargate/).\n- Static assets (JS, CSS, public folder) are stored and served from [Amazon Simple Storage Service (S3)](https://aws.amazon.com/s3/) for all constructs (except `NextjsRegionalContainers`) to decrease latency and reduce compute costs by serving directly from S3.\n- [Optimized images](https://nextjs.org/docs/pages/building-your-application/optimizing/images), [data cache](https://nextjs.org/docs/app/building-your-application/caching#data-cache), [full route cache](https://nextjs.org/docs/app/building-your-application/caching#full-route-cache) and [`'use cache: remote'`](https://nextjs.org/docs/app/api-reference/directives/use-cache-remote) are shared across compute with [Amazon Simple Storage Service (S3)](https://aws.amazon.com/s3/) with supporting metadata in [Amazon DynamoDB](https://aws.amazon.com/dynamodb), and `revalidateTag`/`revalidatePath` reach plain [`'use cache'`](https://nextjs.org/docs/app/api-reference/directives/use-cache) on every instance. See [`'use cache'` and `'use cache: remote'`](#use-cache-and-use-cache-remote).\n- Customize every construct via `overrides`.\n- AWS security and operational best practices are utilized, guided by [cdk-nag](https://github.com/cdklabs/cdk-nag).\n- First class support for [monorepos](https://monorepo.tools/).\n- [Bring Your Own Resources](#bring-your-own-resources) — import existing AWS resources (CloudFront distributions, ECS clusters, ALBs, S3 buckets, DynamoDB tables).\n- [AWS GovCloud (US)](https://aws.amazon.com/govcloud-us) compatible with `NextjsRegionalFunctions` and `NextjsRegionalContainers`.\n\n## Why\n\nThe simplest path to deploy Next.js is on [Vercel](https://vercel.com/) - the Platform-as-a-Service company behind Next.js. However, deploying to Vercel can be expensive and some developers want all of their workloads running _directly_ on AWS. Developers can deploy Next.js on AWS through [AWS Amplify Hosting](https://docs.aws.amazon.com/amplify/latest/userguide/ssr-Amplifysupport.html), but Amplify does not support all Next.js features and manages AWS resources for you so they cannot be customized. If Amplify meets your requirements we recommend you use it, but if you want to use all Next.js features or want more visibility into the AWS resources then this construct is for you.\n\n## Design Principles\n\n- Integrate through Next.js's official interfaces. Build on the [Deployment Adapter](https://nextjs.org/docs/app/guides/deployment-adapters) API and [`@next/routing`](https://www.npmjs.com/package/@next/routing) rather than Next.js internals, so new Next.js versions rarely break this construct. Where no public interface exists yet, the dependency is listed in [Next.js private APIs](docs/nextjs-private-apis.md).\n- Security first.\n- One architecture does not fit all.\n- Enable customization everywhere.\n\n## Prerequisites\n\n- Next.js app running v16.3 or higher (`next build` fails on older versions). If you don't have one yet - follow [these steps](https://nextjs.org/docs/getting-started) to create one.\n- [AWS Cloud Development Kit](https://docs.aws.amazon.com/cdk/v2/guide/home.html) app either in the same package or separate package. cdk-nextjs supports monorepos.\n- A Docker compatible container engine, but **only** for `NextjsGlobalContainers` and `NextjsRegionalContainers` - we recommend [Rancher Desktop](https://rancherdesktop.io/) with dockerd (moby). The two Functions types deploy zip Lambdas and need no container engine.\n- [Node.js](https://nodejs.org/en) v24 (or LTS)\n\n## Getting Started\n\n1. Install `cdk-nextjs` in the package(s) containing your CDK and Next.js app with `npm i cdk-nextjs`\n2. Deploy your Next.js app to AWS: `cdk deploy`. Make sure you have [AWS credentials](https://docs.aws.amazon.com/cli/v1/userguide/cli-chap-configure.html) configured.\n3. Visit URL printed in terminal (CloudFormation Output) to view your Next.js app!\n\nNo `next.config` change is needed: cdk-nextjs runs `next build` itself, and sets [`NEXT_ADAPTER_PATH`](https://nextjs.org/docs/app/api-reference/config/next-config-js/adapterPath) on that build so Next.js loads cdk-nextjs's [Deployment Adapter](https://nextjs.org/docs/app/guides/deployment-adapters).\n\n### Registering the adapter yourself\n\nSet `adapterPath` in `next.config` in three cases. An explicit `adapterPath` always wins over `NEXT_ADAPTER_PATH`, so this is also how you pin a specific adapter.\n\n- **cdk-nextjs isn't running your build** — `skipBuild: true`, or you build in CI and hand the output to CDK.\n- **cdk-nextjs isn't a dependency of the Next.js app**, only of the CDK app. cdk-nextjs resolves the adapter from your app's directory, so it can't find it in that layout.\n- **cdk-nextjs is linked from outside your project root** — a `link:`/`file:` dependency on a checkout elsewhere on disk, as this repo's own examples use. The symlink resolves out of the project, and the adapter derives its cache handler path from its own location, so Next.js gets a `cacheHandler` outside `turbopack.root` and Turbopack rejects it. Setting `adapterPath` fixes this because the build resolves it, after whatever put the adapter in place.\n\n```ts\nimport { NextConfig } from \"next\";\n\nconst nextConfig: NextConfig = {\n // ...\n adapterPath: require.resolve(\"cdk-nextjs/adapter\"),\n};\n\nexport default nextConfig;\n```\n\n`require.resolve` works in an ESM `next.config.ts` too, because Next.js transpiles the config to CJS before evaluating it.\n\n### cdk-nextjs Created Dockerfile\n\nFor the Containers types, cdk-nextjs generates a Dockerfile in your Next.js app's directory. It cannot clean the file up after the image is built, so either commit it or gitignore it.\n\nEvery generated Dockerfile starts with the line `# ~~ Generated by cdk-nextjs ~~`, and cdk-nextjs **overwrites** any file carrying it — that way an upgrade that changes how the image is built does not leave a stale Dockerfile behind. To customize it, delete that first line; cdk-nextjs then leaves the file alone. If you edited a generated file without deleting the header, cdk-nextjs saves your version beside it as `<name>.Dockerfile.bak` before replacing it; gitignore that too.\n\n## Basic Example CDK App\n\n```ts\nimport { App, Stack, StackProps } from \"aws-cdk-lib\";\nimport { Construct } from \"constructs\";\nimport { NextjsGlobalFunctions } from \"cdk-nextjs\";\nimport { join } from \"node:path\";\n\nclass WebStack extends Stack {\n constructor(scope: Construct, id: string, props?: StackProps) {\n super(scope, id, props);\n new NextjsGlobalFunctions(this, \"Nextjs\", {\n buildDirectory: join(import.meta.dirname),\n });\n }\n}\n\nconst app = new App();\n\nnew WebStack(app, \"web-stack\");\n```\n\nSee [examples/](./examples/) for more usage examples.\n\n## Architecture\n\nHow requests are served inside the compute — the adapter runtime, and where it deliberately differs from `next start` — is in [docs/adapter-runtime.md](./docs/adapter-runtime.md).\n\n### `NextjsGlobalFunctions`\n\nArchitecture includes [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html) Functions to respond to dynamic requests and [CloudFront](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Introduction.html) Distribution to globally serve requests and distribute static assets. Use this construct when you have unpredictable traffic, can afford occasional latency (i.e. cold starts - [typically 1% of production traffic](https://aws.amazon.com/blogs/compute/operating-lambda-performance-optimization-part-1/)), and/or want the most granular pricing model. ([code](./src/root-constructs/nextjs-global-functions.ts))\n\n\n\n### `NextjsGlobalContainers`\n\nArchitecture includes [ECS Fargate](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AWS_Fargate.html) containers to respond to dynamic requests and [CloudFront](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Introduction.html) Distribution to globally serve requests and distribute static assets. Use this option when you have predictable traffic, need the lowest latency, and/or can afford a less granular pricing model. ([code](./src/root-constructs/nextjs-global-containers.ts))\n\n\n\n### `NextjsRegionalContainers`\n\nArchitecture includes [ECS Fargate](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AWS_Fargate.html) containers to respond to dynamic requests and [Application Load Balancer](https://aws.amazon.com/elasticloadbalancing/application-load-balancer/) to regionally serve requests. Use this options when you cannot use Amazon CloudFront (i.e. [AWS GovCloud](https://aws.amazon.com/govcloud-us/?whats-new.sort-by=item.additionalFields.postDateTime&whats-new.sort-order=desc)). ([code](./src/root-constructs/nextjs-regional-containers.ts#L41))\n\n\n\n### `NextjsRegionalFunctions`\n\nArchitecture includes [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html) Functions to respond to dynamic requests and [API Gateway REST API](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-rest-api.html) to regionally serve requests and distribute static assets. Use this options when you cannot use Amazon CloudFront (i.e. [AWS GovCloud](https://aws.amazon.com/govcloud-us/?whats-new.sort-by=item.additionalFields.postDateTime&whats-new.sort-order=desc)). ([code](./src/root-constructs/nextjs-regional-functions.ts))\n\n\n\n## Configuration\n\nThe variables below are read at runtime by the cache handler inside your deployed\nLambda functions or containers. Set them on the compute through `overrides`:\n\n```ts\n// NextjsGlobalFunctions / NextjsRegionalFunctions\noverrides: {\n nextjsFunctions: {\n functionProps: { environment: { CDK_NEXTJS_MEMORY_CACHE_TTL_MS: \"0\" } },\n },\n},\n\n// NextjsGlobalContainers / NextjsRegionalContainers\noverrides: {\n nextjsContainers: {\n taskImageOptions: { environment: { CDK_NEXTJS_MEMORY_CACHE_TTL_MS: \"0\" } },\n },\n},\n```\n\nValues you pass are merged over the ones the construct sets, so the same mechanism\noverrides the [infrastructure variables](#infrastructure-configuration) too.\n\n### Cache Configuration\n\n#### `CDK_NEXTJS_MEMORY_CACHE_TTL_MS`\n\nTime to live in milliseconds for in-memory cache entries. After this duration, entries expire and are removed from the cache.\n\n**Note**: Every memory hit is checked against the tag revalidation markers, so an entry revalidated on another instance is not served from memory. A tag's marker is read from DynamoDB only on its first use and a rolling re-read every few minutes; in between, revalidations arrive through the revalidation log (one `Query` per [`CDK_NEXTJS_TAG_REFRESH_MS`](#cdk_nextjs_tag_refresh_ms)). Memory still saves the S3 read and body parse. Set this to `0` to disable the memory cache entirely (all requests will fall through to S3 + DynamoDB).\n\n**Default**: `3600000` (1 hour)\n\n**Examples**:\n\n- Short TTL (5 minutes): `300000` - for frequently changing data\n- Medium TTL (1 hour): `3600000` - balanced between freshness and performance\n- Long TTL (24 hours): `86400000` - for mostly static content\n\n**Trade-offs**:\n\n- Lower values: More cache misses, fresher data, higher S3/DynamoDB costs\n- Higher values: Fewer cache misses, better performance, but longer stale data windows\n\n#### `CDK_NEXTJS_MEMORY_CACHE_MAX_ENTRIES`\n\nMaximum number of cache entries to store in memory. When this limit is reached, the least recently used (LRU) entry is evicted.\n\n**Default**: `1000`\n\n**Examples**:\n\n- Small cache: `100` - minimal memory footprint for simple apps\n- Medium cache: `1000` - good balance for typical applications\n- Large cache: `10000` - for high-traffic apps with many unique pages\n\n**Trade-offs**:\n\n- Lower values: Less memory usage, more cache evictions\n- Higher values: More memory usage, fewer cache evictions, better hit rates\n\n**Memory considerations**: Each entry stores the full cache value (HTML, JSON, etc.). A typical page cache might be 10-100KB, so 1000 entries ≈ 10-100MB of memory. Consider your compute environment's memory limits (Lambda: 128MB-10GB, Fargate: 512MB-30GB) and size accordingly.\n\n### `'use cache'` and `'use cache: remote'`\n\nThe adapter registers two [`cacheHandlers`](https://nextjs.org/docs/app/api-reference/config/next-config-js/cacheHandlers)\nnext to the `cacheHandler` it already sets, unless your `next.config` names a\nhandler of its own for either:\n\n| Directive | `cacheHandlers` name | Stored | Tags |\n| --------------------- | -------------------- | -------------------------------- | ----------------------- |\n| `'use cache'` | `default` | each instance's memory | DynamoDB, all instances |\n| `'use cache: remote'` | `remote` | S3 cache bucket, memory in front | DynamoDB, all instances |\n\n- **`'use cache: remote'`** is shared: an entry any instance generates is the one\n every instance serves, until it expires or a tag is revalidated. Use it for\n results you don't want each Lambda instance or task to compute on its own. It\n costs an S3 `GetObject` the first time an instance reads an entry, and a\n `PutObject` per generated entry. Objects live under\n `<buildId>/_use-cache/` in the cache bucket and are pruned with the build.\n- **`'use cache'`** stays per instance, as Next.js intends — but `revalidateTag`,\n `updateTag` and `revalidatePath` now expire it on every instance, not only the\n one that ran them. Next.js's built-in handler keeps tags in process memory, so\n before this every other instance kept serving the revalidated value, even into\n pages re-rendered because of that revalidation.\n\nBoth read the same per-tag marker rows in the revalidation table that ISR and\nthe data cache use. A tag an instance has not seen yet — an entry read from S3,\na page's implicit `revalidatePath` tags — is read from its marker before it is\ntrusted, once per instance.\n\nAfter that, an instance doesn't re-read the tags it tracks to learn what\nchanged. Each `revalidateTag`/`updateTag` also writes a row to a revalidation\nlog in the same table (`pk = <buildId>#log`, expiring after 15 minutes through\nthe table's `ttl` attribute). At most once per\n[`CDK_NEXTJS_TAG_REFRESH_MS`](#cdk_nextjs_tag_refresh_ms),\neach instance sends one DynamoDB `Query` for the rows written since its last\none and applies those for tags it tracks. So a revalidation on another instance\nis honored within that window (1 second by default), and on the instance that ran\nit immediately. An idle instance's query costs 0.5 RCU a second, where\nre-reading up to 1000 tracked tags cost about 500. Each tag's marker is still\nre-read every 7.5 to 10 minutes, a few each second rather than all at once (about 8\nRCU a second at the most an instance tracks, 10,000 tags). After a gap the log\nmay no longer cover (a Lambda frozen between invocations, a run of failed\nqueries), an instance forgets its tracked markers and reads each again as it's\nneeded. ISR and the data cache share the same copy of the markers, so one\n`revalidateTag` writes each tag's rows once and one `Query` serves them all.\n\nIf you pass your own `revalidationTable`, enabling TTL on its `ttl` attribute is\nrecommended. Without it the log rows (about 100 bytes per revalidated tag) are\nkept until a deploy replaces their build, whose post-deploy step deletes them.\n\nTwo instances that generate the same `'use cache: remote'` entry at the same\nmoment both store it; each serves its own copy until that copy's `revalidate`\ntime, after which S3's is used.\n\n#### `CDK_NEXTJS_TAG_REFRESH_MS`\n\nHow often, at most, in milliseconds, an instance asks the revalidation log what\nother instances revalidated, for `'use cache'`, ISR and the data cache alike. A\n`revalidateTag` elsewhere goes unseen for up to about the window plus a second\n(2 s by default), since `'use cache'` doesn't wait for the answer - and for\nlonger while a query is slow or failing, or for a page render that started\ninside the window, which reads what the instance knew when it began. It's one DynamoDB `Query`,\nhowever many tags the instance tracks, shared by every request on the instance\nduring the window. `0` asks before every cache check, and waits for the answer\n(`'use cache'` only while the instance holds an entry the answer could expire).\nOtherwise `'use cache'` reads don't wait for it, and it applies from the\ninstance's next request. The exception is an instance that hasn't caught up for\nover a second past the window (it sat idle or was frozen): it waits for the\nanswer, before rendering the page for a page request. `'use cache: remote'`\nalways waits.\n\n**Default**: `1000`\n\n#### `CDK_NEXTJS_USE_CACHE_MEMORY_BYTES`\n\nSize bound, in bytes, of each handler's in-memory store: all of `'use cache'`,\nand the memory tier in front of S3 for `'use cache: remote'`. Least recently used\nentries are evicted first.\n\n**Default**: `52428800` (50 MB, Next.js's own default)\n\n### Infrastructure Configuration\n\nThe construct sets these itself and they typically don't need to be modified:\n\n#### `CDK_NEXTJS_BUILD_ID`\n\nUnique identifier for the Next.js build. Used for cache isolation between deployments.\n\n#### `CDK_NEXTJS_CACHE_BUCKET_NAME`\n\nS3 bucket name for storing cached data (optimized images, data cache, full route cache, `'use cache: remote'`).\n\n#### `CDK_NEXTJS_REVALIDATION_TABLE_NAME`\n\nDynamoDB table name for tracking cache revalidations and tag-to-cache-key mappings.\n\n#### `DEBUG`\n\nNot set by default. Set it to `cdk-nextjs:*` to enable debug logs. This is especially useful to see cache handler activity.\n\n### `next.config.js` options cdk-nextjs reads\n\nBoth are read out of your build, so you set them in one place — your app — and the\ninfrastructure follows.\n\n#### `basePath`\n\nBecomes the S3 key prefix for static assets and the prefix on every CloudFront\ncache behavior. See [Resource Isolation](#resource-isolation); the `basePath`\nprop only exists to be explicit about it.\n\n#### `assetPrefix`\n\n- **A path** (`assetPrefix: \"/cdn\"`) — Next.js emits bundle URLs as\n `/cdn/_next/static/...`, on top of `basePath` rather than under it, while the\n objects stay in S3 under `<basePath>/_next/static/...`. `NextjsGlobalFunctions`\n and `NextjsGlobalContainers` add a cache behavior for\n `<assetPrefix>/_next/static*` pointing at the assets bucket, with a CloudFront\n Function that rewrites the prefix back to the S3 keys. It costs one of the 25\n cache behaviors cdk-nextjs budgets for you. **Not supported on\n `NextjsRegionalFunctions` or `NextjsRegionalContainers`** — nothing there maps\n the prefix back, so bundles would 404; synth warns if your app sets one.\n- **An absolute URL** (`assetPrefix: \"https://cdn.example.com\"`) — names an origin\n cdk-nextjs doesn't serve, so nothing is added, on any construct. Point that host\n at the assets bucket yourself, including the `basePath` prefix the objects are\n stored under.\n- **An absolute URL with a path** (`assetPrefix: \"https://cdn.example.com/cdn\"`) —\n its path is treated exactly like the path case above, because `next build`\n compiles a `/cdn/_next/:path+` rewrite of its own: `next start` serves bundles\n under that path too, so the Global constructs answer there as well. Useful when\n that host is a second domain on the same distribution.\n\n## Splitting a Large App Across Functions\n\nOnly for `NextjsGlobalFunctions` and `NextjsRegionalFunctions`, and only if you\nneed it. AWS Lambda caps a function's unzipped code at 250 MB. If your app\nexceeds it, cdk-nextjs fails at synth with the measured size and points you here:\n\n```\nFunction group \"default\" is 274 MB unzipped, over Lambda's 250 MB limit. Use the\n`functionGroups` prop to package routes into separate functions. Note that\nsplitting only removes route-local code — anything reachable from a shared layout\nor the `next` runtime is in every group.\n```\n\n`functionGroups` declares which routes get their own Lambda. Everything you do\nnot name stays on the `default` function:\n\n```ts\nnew NextjsGlobalFunctions(this, \"Nextjs\", {\n buildDirectory: join(import.meta.dirname, \"..\", \"web\"),\n functionGroups: [\n { name: \"reports\", routes: [\"/dashboard/reports/**\"] },\n { name: \"admin\", routes: [\"/admin\", \"/admin/**\", \"/settings\"] },\n ],\n});\n```\n\nEach group becomes one Lambda function containing only the routes it owns (plus\nthe framework closure every function needs), and one CloudFront behavior — or API\nGateway resource, for `NextjsRegionalFunctions` — per pattern.\n\n**Route patterns** are either an exact path (`/settings`) or a subtree\n(`/admin/**`). A subtree owns what is _under_ it, not the path itself:\n`/admin/**` does not claim `/admin`. To own a page and everything under it, list\nboth, as the example above does: `[\"/admin\", \"/admin/**\"]`. Where two groups\ncould both match, the longest pattern wins, so `/api/**` and `/api/reports/**`\ncan coexist in different groups. Dynamic segments (`/blog/[slug]`), route group\nsegments (`/(marketing)/about`), `/`, and `/**` are rejected at synth —\nCloudFront matches literal path prefixes and cannot express them. `/index` is\naccepted for an App Router `app/index/page.tsx`, but not for a Pages Router home\npage, which is the same file as `/`.\n\n**What is routed for you.** Patterns decide which _files_ a group packages; the\nedge then has to send every URL those files serve to that group. cdk-nextjs\nderives these without extra patterns:\n\n- A Pages Router page's data URL, `/_next/data/<buildId>/<page>.json`. The\n behavior carries the literal build ID, so it changes on every deploy; a\n client still on the previous build falls through to the `default` function,\n which answers 404, and the Next.js client reloads the page.\n- The `trailingSlash` form of an exact pattern (`/pricing/`). CloudFront gets a\n behavior for it; on `NextjsRegionalFunctions` none is needed, because API\n Gateway already routes `/pricing/` to the `/pricing` resource.\n- The parent of an optional catch-all. `/shop/**` moving\n `app/shop/[[...slug]]/page.tsx` also routes `/shop`, which the same file\n serves. Do not add `/shop` yourself: it matches no route and is rejected.\n- An [interception route](https://nextjs.org/docs/app/api-reference/file-conventions/intercepting-routes)\n is packaged with the group that owns the URL it intercepts, not by its own\n path: `app/feed/(..)photo/[id]` follows `/photo/[id]`, because a soft\n navigation requests `/photo/1` and Next.js rewrites it in whichever function\n receives it.\n\n**What synth rejects.** After assigning routes, cdk-nextjs replays the\nCloudFront behaviors over every URL each file serves and fails when one would\nreach a function without its file, naming the file, the URL and the pattern to\nadd. That covers:\n\n- A file behind several templates that a pattern only partly covers — root\n params (`app/[locale]/page.tsx` prerendered as `/en` and `/de`) grouped with\n `/en` alone. A dynamic first segment can never be routed, so such a file stays\n in `default`.\n- An intercepted URL space split between groups (`/photo/[id]` in one,\n `/photo/1` in another), since the intercepting file cannot be in both.\n- A `next.config` rewrite whose source reaches one group and whose destination\n file is in another: rewrites run inside the function that received the\n request. Only rewrites with a literal destination are checked.\n- A group pattern that duplicates a top-level `public/` entry's behavior\n (`public/docs/` and `/docs/**`), or sits under one (`/docs/guide/**`), which\n would send the group's routes to S3.\n\nNot checked, because it is only known at request time: **a middleware\n`NextResponse.rewrite()`** to a route in another group reaches the function that\nreceived the original URL, which lacks the route's file. It answers 404 (or a\n308 to the canonical URL when only the case differs) and logs a warning naming\nthe group that owns the route. Keep a middleware rewrite's source and\ndestination in the same group. The same goes\nfor a `next.config` rewrite whose destination is built from its parameters\n(`/b/:slug` → `/blog/:slug`), and for a dynamic segment of a `default` route\nthat overlaps a group's literal path (`/[section]/intro` against `/docs/**`).\nLikewise **a Pages Router `res.revalidate()`** renders the page in the function\nthat called it, so it can only revalidate pages in its own group; the error\nnames the group that owns the page. Use `revalidatePath()` or `revalidateTag()`\nacross groups. And **an `<Image>` whose `src` is a route in another group**\n(`/api/avatar/42` under an `/api/**` group) can't be optimized: `/_next/image`\nruns in the `default` function, which fetches a local source that isn't a\n`public/` or `_next/static` file by running its route in-process, and it doesn't\ncarry that route, so the image request fails. Keep image-serving routes in\n`default`, or point `src` at a `public/` file or a remote URL.\n\n**What splitting does and does not save.** Every function ships the same `next`\nruntime closure, so splitting only moves route-_local_ code and its dependencies.\nA group whose routes import a large library is worth extracting; splitting an app\nin half does not halve either function.\n\nNotes:\n\n- Group names must be valid CDK construct ids (letters, digits, `-`). `default`\n is reserved.\n- A pattern that matches no route in the build is a synth error, not a silent\n no-op — it is almost always a typo.\n- Cannot be combined with `i18n`: locale-prefixed routes would need one\n CloudFront behavior per locale per pattern.\n- Group patterns (and the routes derived from them above) count against the\n same CloudFront behavior budget as your `public/` entries (see\n [Limitations](#limitations)).\n- Per-group `overrides` let you size each function independently:\n `{ name: \"reports\", routes: [...], overrides: { functionProps: { memorySize: 2048 } } }`.\n\n## Running Code on Every Viewer Request\n\n`NextjsGlobalFunctions` and `NextjsGlobalContainers` take a\n`viewerRequestFunctionCode` prop: CloudFront Function code that runs first on\nevery request, on every behavior cdk-nextjs adds — pages, API routes,\n`_next/image`, `_next/static` and `public/` files alike. It's the place for a\ngate the whole site has to pass, such as HTTP Basic auth before launch:\n\n```ts\nimport { FunctionCode, KeyValueStore } from \"aws-cdk-lib/aws-cloudfront\";\n\nconst credentials = new KeyValueStore(this, \"Credentials\");\nnew NextjsGlobalFunctions(this, \"Nextjs\", {\n buildDirectory: join(import.meta.dirname),\n viewerRequestKeyValueStore: credentials,\n viewerRequestFunctionCode: FunctionCode.fromInline(`\n import cf from \"cloudfront\";\n const kvs = cf.kvs();\n async function viewerRequest(event) {\n const auth = event.request.headers.authorization;\n try {\n if (auth && auth.value === \"Basic \" + (await kvs.get(\"basic-auth\"))) {\n // verified: don't pass the site's credentials on to the origin\n delete event.request.headers.authorization;\n return;\n }\n } catch (e) {\n // no \"basic-auth\" key yet: stay locked\n }\n return {\n statusCode: 401,\n statusDescription: \"Unauthorized\",\n headers: { \"www-authenticate\": { value: 'Basic realm=\"preview\"' } },\n };\n }\n `),\n});\n```\n\nThen put the credentials in the store, outside the template:\n\n```sh\nKVS_ARN=... # the store's ARN\naws cloudfront-keyvaluestore put-key --kvs-arn \"$KVS_ARN\" \\\n --key basic-auth --value \"$(printf 'user:pass' | base64 | tr -d '\\n')\" \\\n --if-match \"$(aws cloudfront-keyvaluestore describe-key-value-store \\\n --kvs-arn \"$KVS_ARN\" --query ETag --output text)\"\n```\n\nThe code must define `viewerRequest(event)`, as a function (`async` or not)\nor a `var`/`let`/`const`. It's a CloudFront Function handler in all but name:\nreturn a response to answer the viewer, or the request (or nothing) to carry\non.\n\nWhy not a function of your own on viewer-request? CloudFront allows one per\nevent type per behavior, and on Global Functions cdk-nextjs's own one\noverwrites `X-Forwarded-Host` and redirects repeated slashes. So your code is\nspliced into that function, ahead of cdk-nextjs's logic, which still runs after\nit, so your code can't undo the `X-Forwarded-Host` overwrite. Middleware can't\ndo this instead: on Global Functions CloudFront signs the request to the\nFunction URL with the `Authorization` header, and static assets never reach the\nserver at all.\n\n- cdk-nextjs's CloudFront Functions run on `cloudfront-js-2.0`, so your code\n can be `async`, and `import cf from \"cloudfront\"` works when it comes first,\n as it does above.\n- `viewerRequestKeyValueStore` is associated with every viewer-request function\n your code is copied into (up to three, one per kind of behavior), so\n `cf.kvs()` reads it with no ID wherever the code runs. Credentials written\n inline in the code instead end up in the CloudFormation template.\n- The combined function, cdk-nextjs's code included, must fit CloudFront's\n 10 KB limit; synth fails if it doesn't (or warns, if the code contains a\n CDK token, whose size isn't known until deploy).\n- Your code shares the file with cdk-nextjs's `handler`, so it can't use the\n name `handler` at all, even in a comment or a string; synth refuses it.\n- A viewer-request association in `overrides.*BehaviorOptions.functionAssociations`\n on a behavior this covers is refused at synth; put that logic in\n `viewerRequestFunctionCode` instead. So is\n `overrides.distributionProps.defaultBehavior` without a `basePath`, since it\n would replace the default behavior the code runs on; customize it through\n `overrides.dynamicBehaviorOptions`.\n- A bring-your-own `distribution`'s default behavior is yours, so it isn't\n covered. Only the behaviors cdk-nextjs adds are; under a `basePath`, those\n include the ones that stand in for the default behavior.\n\n## Bring Your Own Resources\n\ncdk-nextjs supports importing existing AWS resources instead of creating new ones. This is especially useful for per-branch (MR/PR) environments where you deploy shared infrastructure (VPC, ECS cluster, ALB) once and spin up lightweight branch stacks that reuse it.\n\n### Supported Resources\n\n| Resource | Prop | Available On |\n| --------------------------- | -------------------- | ---------------------------------------------------- |\n| S3 Cache Bucket | `cacheBucket` | All constructs |\n| DynamoDB Revalidation Table | `revalidationTable` | All constructs |\n| S3 Static Assets Bucket | `staticAssetsBucket` | All constructs |\n| CloudFront Distribution | `distribution` | `NextjsGlobalFunctions`, `NextjsGlobalContainers` |\n| ECS Cluster | `ecsCluster` | `NextjsGlobalContainers`, `NextjsRegionalContainers` |\n| ALB | `alb` | `NextjsGlobalContainers`, `NextjsRegionalContainers` |\n\n### Resource Isolation\n\n- **Cache bucket and DynamoDB table** must be dedicated to one deployment. Sharing either between deployments (branches, stages, apps) is not supported: each deploy's post-deploy step prunes every cache object and revalidation entry that isn't from its own current build, so deploying one branch wipes the others' caches. Buckets and tables are cheap, so give each deployment its own, or leave `cacheBucket`/`revalidationTable` unset and let cdk-nextjs create them (they are removed with the stack).\n- **Static assets bucket** can be shared, but only between deployments with different `basePath`s, which become their S3 key prefixes. Pruning only looks at `<basePath>/_next/`, so it never touches another prefix. Two deployments under the same prefix (for example two subdomain previews both at the root) overwrite each other's `public/` files and prune each other's `_next/` assets once they are past the prune TTL (30 days by default), so give those their own buckets. `NextjsGlobalFunctions` and `NextjsGlobalContainers` read the `basePath` out of your Next.js build and use it as the S3 key prefix, since CloudFront serves assets from S3 by request path and the two can't differ. Set the `basePath` prop only if you want to be explicit about it; a value that disagrees with your app's fails at synth. Each deployment also adds an ownership tag per static asset upload (1 to 3, by whether the build has `public/` files and service workers) to a bucket created in your CDK app; an imported bucket gets none. S3 allows 50 tags per bucket, so such a bucket holds at least 16 deployments.\n\n### Shared ALB and `removeAutoCreatedListener()`\n\n`ApplicationLoadBalancedFargateService` always creates a listener on port 80 — there is no opt-out. When you import an ALB that already has a listener on that port, the duplicate causes a deployment failure. Since CDK doesn't expose a way to prevent this, `removeAutoCreatedListener()` surgically removes the generated CloudFormation resources: the `CfnListener`, its security group ingress rule, rebuilds the ECS service `DependsOn` without the deleted listener, and removes auto-created `CfnOutput` resources:\n\n```ts\nconst nextjs = new NextjsRegionalContainers(this, \"Nextjs\", {\n // ...\n alb: sharedAlb,\n ecsCluster: sharedCluster,\n});\nnextjs.nextjsContainers.removeAutoCreatedListener();\n```\n\n### Examples\n\nSee [examples/bring-your-own/](./examples/bring-your-own/) for a complete deployable example with a shared VPC, ECS cluster, and ALB, per-branch host-header routing, and a cache bucket, revalidation table, and static assets bucket per branch.\n\n## Preview Environments (Per-Branch Deployments)\n\ncdk-nextjs can deploy ephemeral preview environments per merge request (MR) or pull request (PR). The recommended approach uses subdomain-based routing (`pr-123.app.example.com`) so each preview environment runs the same Next.js build as production — no `basePath` configuration or separate builds required.\n\nSee [examples/bring-your-own/](./examples/bring-your-own/) for a fully deployable example using `NextjsRegionalContainers` with a shared VPC, ALB, and ECS Cluster (connected via SSM Parameter Store), and S3 buckets and a DynamoDB table owned by each branch stack.\n\nEach preview environment needs its own cache bucket and revalidation table (see [Resource Isolation](#resource-isolation)). Since every preview serves the same build at the root, give each its own static assets bucket too. Leaving `cacheBucket`, `revalidationTable`, and `staticAssetsBucket` unset does this: cdk-nextjs creates them in the branch stack and deletes them when it's torn down.\n\n### Prerequisites\n\n- Wildcard DNS record: `*.app.example.com` → your routing layer (ALB, CloudFront, API Gateway)\n- Wildcard ACM certificate: `*.app.example.com`\n\n### Per-Architecture Recommendations\n\n#### `NextjsGlobalContainers` and `NextjsRegionalContainers` (ALB-based)\n\nSubdomain routing via ALB host-based listener rules. This is the fastest and simplest approach. For `NextjsGlobalContainers`, CloudFront forwards the `Host` header to the ALB origin, so the ALB handles all branch routing — no CloudFront changes needed per branch.\n\nSee [examples/bring-your-own/](./examples/bring-your-own/) for the full implementation.\n\n#### `NextjsRegionalFunctions` (API Gateway)\n\nSubdomain routing via API Gateway custom domain mappings.\n\n1. Per branch, deploy a cdk-nextjs stack that creates its own API Gateway, Lambda function, S3 buckets, and DynamoDB table\n2. Create an API Gateway custom domain (`pr-123.app.example.com`) mapped to the branch's API stage\n3. Tear down the branch stack on MR close\n\n#### `NextjsGlobalFunctions` (Lambda + CloudFront)\n\nRequires a separate cdk-nextjs stack per branch, each with its own CloudFront distribution. CloudFront cannot route to different Lambda Function URL origins based on the `Host` header — origin selection is determined by cache behavior path patterns, not request headers.\n\n1. Per branch, deploy a full cdk-nextjs stack that creates its own CloudFront distribution, Lambda function, S3 buckets, and DynamoDB table\n2. Point `pr-123.app.example.com` DNS to the branch's CloudFront distribution\n3. Tear down the branch stack on MR close\n\nNote: CloudFront distributions take several minutes to create/update, so this architecture has the slowest preview environment spin-up time.\n\n## Limitations\n\n- If using `NextjsGlobalFunctions` or `NextjsGlobalContainers` (which use CloudFront), each top level file/directory in `public/` takes a CloudFront cache behavior, and a distribution's default quota is 75 behaviors (cdk-nextjs uses 3 to 6 itself). We recommend you put all of your public assets into one top level directory (i.e. public/static) so you don't reach this limit. If you raise the quota for your account, set `maxCacheBehaviors` on the distribution props (`overrides.nextjsGlobalFunctions.nextjsDistributionProps`, or the Containers equivalent) to match. The synth check only counts the behaviors cdk-nextjs adds, so if you pass your own `distribution` (or add behaviors through `overrides.nextjsDistribution.distributionProps`), lower `maxCacheBehaviors` by the behaviors it already has. See [CloudFront Quotas](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-limits.html) for more information.\n- If using `NextjsGlobalFunctions` or `NextjsGlobalContainers`, on-demand revalidation ([revalidatePath](https://nextjs.org/docs/app/api-reference/functions/revalidatePath), [revalidateTag](https://nextjs.org/docs/app/api-reference/functions/revalidateTag)) creates the CloudFront invalidations for you (so does the Pages Router's `res.revalidate()`, for the page's HTML and `_next/data` copies), but [invalidations](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Invalidation.html) are eventually consistent: until one completes (usually seconds, occasionally minutes), some edge locations can still serve the previous copy.\n - **Burst limit.** CloudFront allows 15 wildcard invalidation paths in progress per distribution, and each page cdk-nextjs invalidates is one wildcard path (`/blog*`). Next.js sends every `revalidatePath`/`revalidateTag` from one request as a single call, one invalidation per cache-life profile, however many pages it covers. A Pages Router `res.revalidate()` sends one invalidation per call, and a page regenerated after a stale-while-revalidate `revalidateTag(tag, profile)` sends one more when it lands. When the quota is full, cdk-nextjs retries the request as a single `/*` (a colder edge, never a stale page). If that is also rejected, it logs `Failed to create CloudFront invalidation` and the page stays stale at the edge until its `s-maxage` expires.\n - **For bulk updates** (a CMS webhook touching many pages), call `revalidateTag` with a tag the pages share, or `revalidatePath` for each page within one request, rather than looping `res.revalidate()`. If you need to know when invalidations are dropped, add a CloudWatch Logs metric filter on that log line.\n- If using `NextjsGlobalFunctions`, a client-supplied `Authorization` header does not reach your app: CloudFront signs each request to the Lambda Function URL with SigV4, which uses that header. Send credentials under a different name (e.g. `x-authorization`) and read that header in your app. cdk-nextjs does not rename it for you — it no longer uses [AWS Lambda Web Adapter](https://github.com/awslabs/aws-lambda-web-adapter), so `AWS_LWA_AUTHORIZATION_SOURCE` no longer applies.\n- If using `NextjsGlobalFunctions`, a `POST` or `PUT` with a request body must carry an `x-amz-content-sha256` header holding the hex SHA-256 of that body. This is [AWS behavior](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-lambda.html), not a cdk-nextjs choice: CloudFront signs the origin request to the Lambda Function URL with SigV4 but does not hash the body, and Lambda rejects an unsigned payload with `403 InvalidSignatureException`. Requests from your own pages are handled for you — cdk-nextjs injects a `fetch`/`XMLHttpRequest` wrapper into the client bundle that adds the header, so server actions, route handlers, `fetch` and `XMLHttpRequest` from the browser work untouched, whatever the body type. The exception is a native `<form method=\"post\">` submitted before the page hydrates (a server action form without JavaScript, or clicked before the bundle loads): the browser sends it, not the wrapper, so it has no header and gets the 403. **Anything that is not that browser bundle has to add the header itself**: `curl`, a mobile app, a webhook provider, another service calling your API routes. Server-to-server callers can compute it with the AWS SDK's `Sha256`, or with `crypto.createHash(\"sha256\").update(body).digest(\"hex\")`. The other three deployment types are unaffected.\n- If using `NextjsGlobalFunctions`, a `HEAD` request is answered with `content-length: 0`, whatever length your handler declares. This is Lambda Function URL behavior: the same runtime's declared length reaches the client through API Gateway (`NextjsRegionalFunctions`) and from an ALB, with or without CloudFront in front (the two Containers types).\n- Group patterns declared via [`functionGroups`](#splitting-a-large-app-across-functions) also count against the CloudFront behavior limit above.\n- If using `NextjsRegionalFunctions` without a custom domain, API Gateway REST APIs require a [stage name](https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-stages.html) (default: `/prod`) to be specified. This causes links to pages and static assets to break because they're not prefixed with the stage name. You can work around this issue by specifying [basePath](https://nextjs.org/docs/app/api-reference/config/next-config-js/basePath) in next.config.js as your stage name — leave the construct's `basePath` prop unset when you do, since API Gateway strips the stage before matching resources. API Gateway strips the stage from the path it passes to Lambda; cdk-nextjs puts it back for an app whose `basePath` starts with it, reading the stage off each request, so no middleware is needed and a renamed stage needs no configuration. Mapping a custom domain at the root avoids all of this — see [examples/regional-functions/README.md](./examples/regional-functions/README.md#with-a-custom-domain-no-stage-workarounds).\n\n## Additional Security Recommendations\n\nThis construct by default implements all AWS security best practices that a CDK construct library reasonably can considering cost and complexity. Below are additional security practices we recommend you implement within your CDK app. Please see them below:\n\n- [VPC Flow Logs](https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html). See [examples/](./examples) for sample implementation.\n- [Scan ECR Images For Vulnerabilities](https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-scanning.html).\n- For `NextjsGlobalFunctions` and `NextjsGlobalContainers`, [CloudFront Access Logs](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html). See [examples/](./examples) for sample implementation.\n- For `NextjsGlobalContainers` and `NextjsRegionalContainers`, use [ALB HTTPS Listener](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html)\n- If using `NextjsGlobalContainers` and `NextjsRegionalContainers`, enable `ReadonlyRootFilesystem`. This will remove ability to use Static On-Demand feature of Next.js so it's not enabled by default, but is recommended for security.\n\n## Estimated Costs\n\n### Assumptions\n\nThe following basic assumptions were used for a typical medium Next.js app. See [docs/usage.xlsx](./docs/usage.xlsx) for detailed assumptions and usage per construct type that you can plug into AWS Pricing Calculator.\n\n| Metric | Value |\n| ------------------------------------------------------------ | ----- |\n| Monthly Active Users | 1K |\n| Pages Visited Per Month Per User | 100 |\n| Avg Request Size | 50KB |\n| Static Requests Per Page (js, css, etc) | 15 |\n| Static Requests Cache Hit % | 50% |\n| Static Assets Size | 10GB |\n| Dynamic Requests Per Page (document, optimized images, etc.) | 5 |\n| Dynamic Cache Read % | 50% |\n| Dynamic Cache Write % | 5% |\n| Dynamic Cache Data Size | 10GB |\n| Average Dynamic Cache Request Size | 100KB |\n| Dynamic Revalidate Tag % | 1% |\n\nMore Details:\n\n- Assume ARM architecture for compute\n- AWS Region: us-east-1\n- Excludes charges related to: CloudWatch Logs, NAT Gateway data processing\n\n### NextjsGlobalFunctions\n\n[AWS Pricing Calculator](https://calculator.aws/#/estimate?id=23611f6fea87ef05d5fe87c33135ddde43b17a98)\n\n| Service | Monthly Usage | Estimated Monthly Cost (USD) |\n| ---------- | ---------------------------------------------- | ---------------------------- |\n| Lambda | 500K requests, 2 GB memory, 150ms avg duration | $0.00 (Always Free Tier) |\n| CloudFront | 2M requests, 100 GB transfer to internet | $0.00 (Always Free Tier) |\n| S3 | 20 GB storage, 1M GET, 250K PUT requests | $2.11 |\n| DynamoDB | 10 GB storage, 5K Reads, 5K Writes | $2.50 |\n| Total | | $8.09 |\n\n### NextjsGlobalContainers\n\n[AWS Pricing Calculator](https://calculator.aws/#/estimate?id=02f0073e612d1eee2a7ccace2c636adc5f0acab7)\n\n| Service | Monthly Usage | Estimated Monthly Cost (USD) |\n| ----------- | ---------------------------------------- | ---------------------------- |\n| ECS Fargate | 1 task (1 vCPU, 2 GB) | $28.44 |\n| ALB | 1 LB, 1.04GB/hr, 5.79 conn/sec | $22.50 |\n| CloudFront | 2M requests, 100 GB transfer to internet | $0.00 (Always Free Tier) |\n| S3 | 20 GB storage, 1M GET, 250K PUT requests | $2.11 |\n| DynamoDB | 10 GB storage, 5K Reads, 5K Writes | $2.50 |\n| VPC | NAT Gateway, 2 AZs | $65.70 |\n| Total | | $121.25 |\n\n### NextjsRegionalContainers\n\n[AWS Pricing Calculator](https://calculator.aws/#/estimate?id=e214abe60eb4e24fc5866d07ef4355393261af3c)\n\n| Service | Monthly Usage | Estimated Monthly Cost (USD) |\n| ----------- | ------------------------------------------ | ---------------------------- |\n| ECS Fargate | 1 task (2 vCPU, 4 GB), always on | $28.44 |\n| ALB | 1 LB, 4.17 GB/hr, 23.15 conn/sec | $40.78 |\n| S3 | 10 GB storage, 250K GET, 250K PUT requests | $1.58 |\n| DynamoDB | 10 GB storage, 5K Reads, 5K Writes | $2.50 |\n| VPC | NAT Gateway, 2 AZs | $65.70 |\n| Total | | $139.00 |\n\n### NextjsRegionalFunctions\n\n[AWS Pricing Calculator](https://calculator.aws/#/estimate?id=60da38c7993c1baeee2fee4bd19ba6441608bb15)\n\n| Service | Monthly Usage | Estimated Monthly Cost (USD) |\n| ----------- | ---------------------------------------------- | ---------------------------- |\n| Lambda | 500K requests, 2 GB memory, 150ms avg duration | $0.00 (Always Free Tier) |\n| API Gateway | 2M requests | $7.00 |\n| S3 | 10 GB storage, 250K GET, 250K PUT requests | $1.58 |\n| DynamoDB | 10 GB storage, 5K Reads, 5K Writes | $2.50 |\n| Total | | $11.08 |\n\n## Performance\n\nMeasured with [k6](https://grafana.com/docs/k6/latest/) from EC2 in us-east-1, the region of the stacks under test (one load generator per stack), against a small benchmark app ([`examples/bench-app`](./examples/bench-app)) that makes no calls outside its own stack. Functions run the default 2048 MB Lambda functions. Containers run the default 1 vCPU / 2 GB Fargate tasks, with CPU autoscaling from 2 to 10 tasks added (the default is one task and no autoscaling). Methodology, caveats, and how to reproduce the numbers: [`examples/load-tests`](./examples/load-tests).\n\nWhat each route measures:\n\n- `static-asset`, `static`, `image`: CloudFront's cache on the Global constructs, and the construct itself on the Regional ones.\n- `isr`: the cache until the page is stale (10 s), then a background revalidation through the S3 + DynamoDB cache.\n- `ssr`, `stream`, `rsc`, `api`: the construct's compute on every request, on every construct.\n\n<!-- tables generated by `pnpm report` in examples/load-tests -->\n\n| Construct | `ssr` at 10 req/s | `ssr` at 50 req/s | `ssr` capacity | `isr` capacity | Cold start p50 |\n| -------------------------- | ----------------- | ----------------------------------------- | -------------- | -------------- | -------------- |\n| `NextjsGlobalFunctions` | 36 / 103 | 33 / 84 | ≥ 6560 req/s | ≥ 6560 req/s | 1390 ms |\n| `NextjsGlobalContainers` | 19 / 44 | 18 / 219 | 194 req/s | ≥ 6400 req/s | – |\n| `NextjsRegionalContainers` | 22 / 172 | 1972 / 39536 ⚠️ 0.54% errors, 76% dropped | 675 req/s | ≥ 6075 req/s | – |\n| `NextjsRegionalFunctions` | 32 / 114 | 30 / 103 | ≥ 6560 req/s | ≥ 6560 req/s | 1380 ms |\n\n_Latency is p50 / p99 in ms, with every route loaded at that rate at once. Capacity is the highest rate sustained with p99 under 1000 ms and under 1% errors._\n\nWhat this means for choosing one:\n\n- **Functions constructs scale with no sizing.** Both held at least 6,560 req/s of SSR, the load generator's limit, at the same latency as at 10 req/s. The cost is a cold start of about 1.4 s on a new execution environment.\n- **Containers constructs are fastest per request but need sizing.** Two 1 vCPU tasks served SSR at 19–22 ms p50 against Lambda's ~30 ms, but tasks take minutes to add. Past capacity they don't degrade gradually: tasks too busy to answer the ALB health check are replaced, which leaves fewer tasks for the same load. Leave headroom.\n- **CloudFront carries the Global constructs' cached traffic.** Prerendered pages, ISR hits, images and assets were answered at the edge in 2–3 ms at every rate. On the Regional constructs every request reaches the construct: `NextjsRegionalContainers` serves assets and image optimization from the same tasks, so 50 req/s on every route at once (400 req/s) is already more than two tasks handle.\n- **Cached pages scale on every construct.** ISR hits held at least 6,000 req/s on all four: at the edge on the Global constructs, and through the S3 + DynamoDB cache on the Regional ones, where each instance holds a tag's revalidation marker for a second (`CDK_NEXTJS_TAG_REFRESH_MS`, see the [Caching Guide](./docs/caching-guide.md)).\n\n<details>\n<summary><code>NextjsGlobalFunctions</code></summary>\n\nLatency per route, p50 / p99 in ms, with every route at the same rate at once:\n\n| Route | 10 req/s | 50 req/s | 250 req/s | 1000 req/s | CDN hits |\n| ------------- | --------- | --------- | --------- | ---------- | -------- |\n| static-asset | 2.1 / 4.8 | 2.1 / 4.7 | 2.0 / 4.9 | 2.1 / 11 | 100% |\n| static | 3.3 / 7.5 | 3.2 / 6.8 | 3.1 / 7.3 | 3.2 / 13 | 100% |\n| isr | 3.3 / 7.4 | 3.3 / 7.7 | 3.2 / 7.2 | 3.2 / 12 | 100% |\n| ssr | 36 / 103 | 33 / 84 | 31 / 86 | 29 / 73 | 0% |\n| stream | 233 / 268 | 230 / 261 | 228 / 259 | 226 / 252 | 0% |\n| stream (TTFB) | 32 / 89 | 29 / 66 | 27 / 65 | 25 / 57 | |\n| rsc | 32 / 67 | 28 / 61 | 27 / 60 | 25 / 52 | 0% |\n| api | 29 / 79 | 26 / 55 | 24 / 61 | 23 / 47 | 0% |\n| image | 3.2 / 6.3 | 3.1 / 6.8 | 3.1 / 7.0 | 3.1 / 12 | 100% |\n\nCapacity: `isr` ≥ 6560 req/s, `ssr` ≥ 6560 req/s.\n\nCold start, time to first byte of `/ssr` on a new execution environment: p50 1390 ms, p90 1451 ms (warm: 84 ms).\n\nBrowser, p75 in ms, under 50 req/s per route:\n\n| Route | LCP | TTFB | Client-side navigation |\n| ------ | --- | ---- | ---------------------- |\n| static | 76 | 13 | 15 |\n| ssr | 80 | 39 | 53 |\n| isr | 52 | 8.7 | 12 |\n| stream | 64 | 34 | 38 |\n| image | 52 | 6.7 | 10 |\n\n</details>\n\n<details>\n<summary><code>NextjsGlobalContainers</code></summary>\n\nLatency per route, p50 / p99 in ms, with every route at the same rate at once:\n\n| Route | 10 req/s | 50 req/s | CDN hits |\n| ------------- | --------- | --------- | -------- |\n| static-asset | 1.4 / 3.9 | 1.5 / 3.7 | 100% |\n| static | 1.9 / 4.8 | 1.8 / 3.7 | 100% |\n| isr | 2.0 / 4.4 | 1.7 / 4.0 | 100% |\n| ssr | 19 / 44 | 18 / 219 | 0% |\n| stream | 217 / 242 | 217 / 359 | 0% |\n| stream (TTFB) | 17 / 45 | 16 / 207 | |\n| rsc | 12 / 26 | 12 / 86 | 0% |\n| api | 11 / 23 | 10 / 81 | 0% |\n| image | 2.0 / 4.7 | 1.7 / 4.1 | 100% |\n\nCapacity: `isr` ≥ 6400 req/s, `ssr` 194 req/s.\n\nBrowser, p75 in ms, under 50 req/s per route:\n\n| Route | LCP | TTFB | Client-side navigation |\n| ------ | --- | ---- | ---------------------- |\n| static | 88 | 12 | 17 |\n| ssr | 80 | 26 | 39 |\n| isr | 56 | 6.1 | 13 |\n| stream | 64 | 20 | 25 |\n| image | 52 | 5.4 | 11 |\n\n</details>\n\n<details>\n<summary><code>NextjsRegionalContainers</code></summary>\n\nLatency per route, p50 / p99 in ms, with every route at the same rate at once:\n\n| Route | 10 req/s | 50 req/s | CDN hits |\n| ------------- | --------- | ----------------------------------------- | -------- |\n| static-asset | 18 / 159 | 1698 / 28824 ⚠️ 0.40% errors, 72% dropped | no CDN |\n| static | 41 / 163 | 916 / 28298 ⚠️ 0.46% errors, 66% dropped | no CDN |\n| isr | 40 / 169 | 697 / 27146 ⚠️ 0.36% errors, 57% dropped | no CDN |\n| ssr | 22 / 172 | 1972 / 39536 ⚠️ 0.54% errors, 76% dropped | no CDN |\n| stream | 221 / 354 | 1909 / 27423 ⚠️ 0.44% errors, 72% dropped | no CDN |\n| stream (TTFB) | 19 / 166 | 1881 / 27162 | |\n| rsc | 9.4 / 64 | 433 / 26066 ⚠️ 0.25% errors, 39% dropped | no CDN |\n| api | 6.9 / 55 | 429 / 26041 ⚠️ 0.25% errors, 38% dropped | no CDN |\n| image | 140 / 440 | 1599 / 27489 ⚠️ 0.22% errors, 69% dropped | no CDN |\n\nCapacity: `isr` ≥ 6075 req/s, `ssr` 675 req/s.\n\nBrowser, p75 in ms, under 10 req/s per route. `static` is each visit's first page: on a plain-HTTP origin, Chrome tries HTTPS first and falls back after about 3 s (HTTPS-Upgrades), which real visitors pay too. Put a certificate on the ALB to avoid it.\n\n| Route | LCP | TTFB | Client-side navigation |\n| ------ | ---- | ---- | ---------------------- |\n| static | 3100 | 3047 | 16 |\n| ssr | 68 | 14 | 27 |\n| isr | 88 | 43 | 13 |\n| stream | 48 | 11 | 13 |\n| image | 212 | 38 | 9.6 |\n\n</details>\n\n<details>\n<summary><code>NextjsRegionalFunctions</code></summary>\n\nLatency per route, p50 / p99 in ms, with every route at the same rate at once:\n\n| Route | 10 req/s | 50 req/s | 250 req/s | 1000 req/s | CDN hits |\n| ------------- | --------- | --------- | --------- | ---------- | -------- |\n| static-asset | 34 / 76 | 32 / 72 | 30 / 72 | 30 / 68 | no CDN |\n| static | 58 / 138 | 57 / 140 | 57 / 147 | 57 / 127 | no CDN |\n| isr | 58 / 149 | 56 / 124 | 56 / 145 | 55 / 125 | no CDN |\n| ssr | 32 / 114 | 30 / 103 | 29 / 115 | 29 / 98 | no CDN |\n| stream | 229 / 293 | 227 / 288 | 227 / 299 | 226 / 282 | no CDN |\n| stream (TTFB) | 27 / 85 | 25 / 84 | 25 / 97 | 24 / 76 | |\n| rsc | 27 / 76 | 26 / 73 | 25 / 83 | 25 / 70 | no CDN |\n| api | 24 / 84 | 22 / 70 | 22 / 97 | 22 / 67 | no CDN |\n| image | 127 / 210 | 125 / 221 | 125 / 236 | 123 / 211 | no CDN |\n\nCapacity: `isr` ≥ 6560 req/s, `ssr` ≥ 6560 req/s.\n\nCold start, time to first byte of `/ssr` on a new execution environment: p50 1380 ms, p90 1442 ms (warm: 71 ms).\n\nBrowser, p75 in ms, under 50 req/s per route:\n\n| Route | LCP | TTFB | Client-side navigation |\n| ------ | --- | ---- | ---------------------- |\n| static | 128 | 70 | 17 |\n| ssr | 88 | 35 | 50 |\n| isr | 108 | 62 | 13 |\n| stream | 64 | 31 | 36 |\n| image | 220 | 60 | 9.6 |\n\n</details>\n\n## Guides\n\n- [Caching Guide](./docs/caching-guide.md)\n- [Pruning Guide](./docs/pruning-guide.md)\n- [Native Dependencies Guide](./docs/native-dependencies-guide.md)\n- [Next Build Output Guide](./docs/next-build-output-guide.ts)\n- [Development Guide](./docs/development-guide.ts)\n\n## Contributing\n\nSteps to build locally:\n\n1. `git clone https://github.com/cdklabs/cdk-nextjs.git`\n2. `cd cdk-nextjs`\n3. `pnpm i && pnpm compile && pnpm build`\n\nThis project uses Projen, so make sure to not edit [Projen](https://projen.io/) created files and only edit .projenrc.ts.\n\n## FAQ\n\nQ: How does this compare to [cdk-nextjs-standalone](https://github.com/jetbridge/cdk-nextjs) or [OpenNext](https://opennext.js.org)?<br/>\nA: cdk-nextjs builds on Next.js's official [Deployment Adapter](https://nextjs.org/docs/app/guides/deployment-adapters) API and runs requests through [`@next/routing`](https://www.npmjs.com/package/@next/routing), the routing library Next.js publishes for platform adapters. Next.js tells cdk-nextjs what it built, and routing follows the same rules as `next start`. Nothing re-implements Next.js's router or patches its server. The few Next.js internals cdk-nextjs does load (the image optimizer and static file server) are loaded as they are, not modified. This keeps upgrades cheap and breaking changes rare. cdk-nextjs is tested against Next.js's own end-to-end test suite; [harness-coverage.md](docs/harness-coverage.md) lists the cases that differ and why.\n\nQ: Why does cdk-nextjs depend upon Next.js v16.3 or higher?\nA: cdk-nextjs builds through the public [Adapter API](https://nextjs.org/docs/app/api-reference/config/next-config-js/adapterPath), and 16.3 is the first version whose build output carries everything it reads (middleware matchers and per-file asset hashes). 16.2 also added the [Image Optimization Caching](https://nextjs.org/docs/app/api-reference/config/next-config-js/incrementalCacheHandlerPath#image-optimization-caching) it relies on. The runtime bundles `@next/routing` at the version it was tested against (see `package.json`), and newer Next.js 16 releases are expected to work.\n\nQ: How does cdk-nextjs support caching in Next.js?<br/>\nA: See [Caching Guide](./docs/caching-guide.md)\n\nQ: How customizable is the `cdk-nextjs` package for different use cases?<br/>\nA: The `cdk-nextjs` package offers deep customization through _prop-based_ overrides. These can be accessed in the construct props, allowing you to override settings like VPC configurations, CloudFront distribution, and ECS/Fargate setup. For example, you can modify `nextjsBuildProps` to customize the build process or use `nextjsDistributionProps` to adjust how CloudFront handles caching and routing. This level of control makes it easy to adapt the infrastructure to your application’s specific performance, networking, or deployment needs.\n\nQ: How can I use a custom domain with `cdk-nextjs`?<br/>\nA: See [low-cost example](./examples/low-cost/app.ts).\n\nQ: What is difference between `NextjsGlobalFunctionsProps.overrides.nextjsDistribution` and `NextjsGlobalFunctionsProps.overrides.nextjsGlobalFunctions.nextjsDistributionProps`<br/>\nA: `NextjsGlobalFunctionsProps.overrides.nextjsDistribution` allows you to customize any construct's props _within_ `NextjsDistribution` and is likely what you want whereas `NextjsGlobalFunctionsProps.overrides.nextjsGlobalFunctions.nextjsDistributionProps` allows you to customize the props passed into the construct: `NextjsDistribution`. This principle also applies to other similarly named overrides.\n\nQ: How can I `cdk bootstrap --cloudformation-execution-policies ...` my AWS Account with limited permissions for cdk-nextjs to deploy?<br />\nA: See [docs/cdk-nextjs-cfn-exec-policy.json](./docs/cdk-nextjs-cfn-exec-policy.json). Note, this IAM Policy is scoped to all cdk-nextjs constructs so you can remove services if you know the construct you're using doesn't use that service.\n\n## Acknowledgements\n\nThis construct was built on the shoulders of giants. Thank you to the contributors of [cdk-nextjs-standalone](https://github.com/jetbridge/cdk-nextjs) and [OpenNext](https://opennext.js.org).\n\n## 🥂 Thanks Contributors\n\nThank you for helping other developers deploy Next.js apps on AWS\n\n<a href=\"https://github.com/cdklabs/cdk-nextjs/graphs/contributors\">\n <img src=\"https://contrib.rocks/image?repo=cdklabs/cdk-nextjs\" />\n</a>\n"
|
|
9036
9036
|
},
|
|
9037
9037
|
"repository": {
|
|
9038
9038
|
"type": "git",
|
|
@@ -11311,7 +11311,7 @@
|
|
|
11311
11311
|
},
|
|
11312
11312
|
"locationInModule": {
|
|
11313
11313
|
"filename": "src/nextjs-distribution.ts",
|
|
11314
|
-
"line":
|
|
11314
|
+
"line": 260
|
|
11315
11315
|
},
|
|
11316
11316
|
"parameters": [
|
|
11317
11317
|
{
|
|
@@ -11337,7 +11337,7 @@
|
|
|
11337
11337
|
"kind": "class",
|
|
11338
11338
|
"locationInModule": {
|
|
11339
11339
|
"filename": "src/nextjs-distribution.ts",
|
|
11340
|
-
"line":
|
|
11340
|
+
"line": 198
|
|
11341
11341
|
},
|
|
11342
11342
|
"name": "NextjsDistribution",
|
|
11343
11343
|
"properties": [
|
|
@@ -11347,7 +11347,7 @@
|
|
|
11347
11347
|
},
|
|
11348
11348
|
"locationInModule": {
|
|
11349
11349
|
"filename": "src/nextjs-distribution.ts",
|
|
11350
|
-
"line":
|
|
11350
|
+
"line": 199
|
|
11351
11351
|
},
|
|
11352
11352
|
"name": "distribution",
|
|
11353
11353
|
"type": {
|
|
@@ -11368,7 +11368,7 @@
|
|
|
11368
11368
|
"kind": "interface",
|
|
11369
11369
|
"locationInModule": {
|
|
11370
11370
|
"filename": "src/nextjs-distribution.ts",
|
|
11371
|
-
"line":
|
|
11371
|
+
"line": 192
|
|
11372
11372
|
},
|
|
11373
11373
|
"name": "NextjsDistributionFunctionGroup",
|
|
11374
11374
|
"properties": [
|
|
@@ -11381,7 +11381,7 @@
|
|
|
11381
11381
|
"immutable": true,
|
|
11382
11382
|
"locationInModule": {
|
|
11383
11383
|
"filename": "src/nextjs-distribution.ts",
|
|
11384
|
-
"line":
|
|
11384
|
+
"line": 195
|
|
11385
11385
|
},
|
|
11386
11386
|
"name": "functionUrl",
|
|
11387
11387
|
"type": {
|
|
@@ -11396,7 +11396,7 @@
|
|
|
11396
11396
|
"immutable": true,
|
|
11397
11397
|
"locationInModule": {
|
|
11398
11398
|
"filename": "src/nextjs-distribution.ts",
|
|
11399
|
-
"line":
|
|
11399
|
+
"line": 193
|
|
11400
11400
|
},
|
|
11401
11401
|
"name": "name",
|
|
11402
11402
|
"type": {
|
|
@@ -11416,7 +11416,7 @@
|
|
|
11416
11416
|
"kind": "interface",
|
|
11417
11417
|
"locationInModule": {
|
|
11418
11418
|
"filename": "src/nextjs-distribution.ts",
|
|
11419
|
-
"line":
|
|
11419
|
+
"line": 68
|
|
11420
11420
|
},
|
|
11421
11421
|
"name": "NextjsDistributionOverrides",
|
|
11422
11422
|
"properties": [
|
|
@@ -11428,7 +11428,7 @@
|
|
|
11428
11428
|
"immutable": true,
|
|
11429
11429
|
"locationInModule": {
|
|
11430
11430
|
"filename": "src/nextjs-distribution.ts",
|
|
11431
|
-
"line":
|
|
11431
|
+
"line": 69
|
|
11432
11432
|
},
|
|
11433
11433
|
"name": "distributionProps",
|
|
11434
11434
|
"optional": true,
|
|
@@ -11444,7 +11444,7 @@
|
|
|
11444
11444
|
"immutable": true,
|
|
11445
11445
|
"locationInModule": {
|
|
11446
11446
|
"filename": "src/nextjs-distribution.ts",
|
|
11447
|
-
"line":
|
|
11447
|
+
"line": 73
|
|
11448
11448
|
},
|
|
11449
11449
|
"name": "dynamicBehaviorOptions",
|
|
11450
11450
|
"optional": true,
|
|
@@ -11460,7 +11460,7 @@
|
|
|
11460
11460
|
"immutable": true,
|
|
11461
11461
|
"locationInModule": {
|
|
11462
11462
|
"filename": "src/nextjs-distribution.ts",
|
|
11463
|
-
"line":
|
|
11463
|
+
"line": 74
|
|
11464
11464
|
},
|
|
11465
11465
|
"name": "dynamicCachePolicyProps",
|
|
11466
11466
|
"optional": true,
|
|
@@ -11476,7 +11476,7 @@
|
|
|
11476
11476
|
"immutable": true,
|
|
11477
11477
|
"locationInModule": {
|
|
11478
11478
|
"filename": "src/nextjs-distribution.ts",
|
|
11479
|
-
"line":
|
|
11479
|
+
"line": 76
|
|
11480
11480
|
},
|
|
11481
11481
|
"name": "dynamicFunctionUrlOriginWithOACProps",
|
|
11482
11482
|
"optional": true,
|
|
@@ -11492,7 +11492,7 @@
|
|
|
11492
11492
|
"immutable": true,
|
|
11493
11493
|
"locationInModule": {
|
|
11494
11494
|
"filename": "src/nextjs-distribution.ts",
|
|
11495
|
-
"line":
|
|
11495
|
+
"line": 75
|
|
11496
11496
|
},
|
|
11497
11497
|
"name": "dynamicResponseHeadersPolicyProps",
|
|
11498
11498
|
"optional": true,
|
|
@@ -11508,7 +11508,7 @@
|
|
|
11508
11508
|
"immutable": true,
|
|
11509
11509
|
"locationInModule": {
|
|
11510
11510
|
"filename": "src/nextjs-distribution.ts",
|
|
11511
|
-
"line":
|
|
11511
|
+
"line": 77
|
|
11512
11512
|
},
|
|
11513
11513
|
"name": "dynamicVpcOriginWithEndpointProps",
|
|
11514
11514
|
"optional": true,
|
|
@@ -11524,7 +11524,7 @@
|
|
|
11524
11524
|
"immutable": true,
|
|
11525
11525
|
"locationInModule": {
|
|
11526
11526
|
"filename": "src/nextjs-distribution.ts",
|
|
11527
|
-
"line":
|
|
11527
|
+
"line": 70
|
|
11528
11528
|
},
|
|
11529
11529
|
"name": "imageBehaviorOptions",
|
|
11530
11530
|
"optional": true,
|
|
@@ -11540,7 +11540,7 @@
|
|
|
11540
11540
|
"immutable": true,
|
|
11541
11541
|
"locationInModule": {
|
|
11542
11542
|
"filename": "src/nextjs-distribution.ts",
|
|
11543
|
-
"line":
|
|
11543
|
+
"line": 71
|
|
11544
11544
|
},
|
|
11545
11545
|
"name": "imageCachePolicyProps",
|
|
11546
11546
|
"optional": true,
|
|
@@ -11556,7 +11556,7 @@
|
|
|
11556
11556
|
"immutable": true,
|
|
11557
11557
|
"locationInModule": {
|
|
11558
11558
|
"filename": "src/nextjs-distribution.ts",
|
|
11559
|
-
"line":
|
|
11559
|
+
"line": 72
|
|
11560
11560
|
},
|
|
11561
11561
|
"name": "imageResponseHeadersPolicyProps",
|
|
11562
11562
|
"optional": true,
|
|
@@ -11572,7 +11572,7 @@
|
|
|
11572
11572
|
"immutable": true,
|
|
11573
11573
|
"locationInModule": {
|
|
11574
11574
|
"filename": "src/nextjs-distribution.ts",
|
|
11575
|
-
"line":
|
|
11575
|
+
"line": 80
|
|
11576
11576
|
},
|
|
11577
11577
|
"name": "s3BucketOriginProps",
|
|
11578
11578
|
"optional": true,
|
|
@@ -11588,7 +11588,7 @@
|
|
|
11588
11588
|
"immutable": true,
|
|
11589
11589
|
"locationInModule": {
|
|
11590
11590
|
"filename": "src/nextjs-distribution.ts",
|
|
11591
|
-
"line":
|
|
11591
|
+
"line": 78
|
|
11592
11592
|
},
|
|
11593
11593
|
"name": "staticBehaviorOptions",
|
|
11594
11594
|
"optional": true,
|
|
@@ -11604,7 +11604,7 @@
|
|
|
11604
11604
|
"immutable": true,
|
|
11605
11605
|
"locationInModule": {
|
|
11606
11606
|
"filename": "src/nextjs-distribution.ts",
|
|
11607
|
-
"line":
|
|
11607
|
+
"line": 79
|
|
11608
11608
|
},
|
|
11609
11609
|
"name": "staticResponseHeadersPolicyProps",
|
|
11610
11610
|
"optional": true,
|
|
@@ -11625,7 +11625,7 @@
|
|
|
11625
11625
|
"kind": "interface",
|
|
11626
11626
|
"locationInModule": {
|
|
11627
11627
|
"filename": "src/nextjs-distribution.ts",
|
|
11628
|
-
"line":
|
|
11628
|
+
"line": 83
|
|
11629
11629
|
},
|
|
11630
11630
|
"name": "NextjsDistributionProps",
|
|
11631
11631
|
"properties": [
|
|
@@ -11639,7 +11639,7 @@
|
|
|
11639
11639
|
"immutable": true,
|
|
11640
11640
|
"locationInModule": {
|
|
11641
11641
|
"filename": "src/nextjs-distribution.ts",
|
|
11642
|
-
"line":
|
|
11642
|
+
"line": 88
|
|
11643
11643
|
},
|
|
11644
11644
|
"name": "assetsBucket",
|
|
11645
11645
|
"type": {
|
|
@@ -11654,7 +11654,7 @@
|
|
|
11654
11654
|
"immutable": true,
|
|
11655
11655
|
"locationInModule": {
|
|
11656
11656
|
"filename": "src/nextjs-distribution.ts",
|
|
11657
|
-
"line":
|
|
11657
|
+
"line": 126
|
|
11658
11658
|
},
|
|
11659
11659
|
"name": "nextjsType",
|
|
11660
11660
|
"type": {
|
|
@@ -11670,7 +11670,7 @@
|
|
|
11670
11670
|
"immutable": true,
|
|
11671
11671
|
"locationInModule": {
|
|
11672
11672
|
"filename": "src/nextjs-distribution.ts",
|
|
11673
|
-
"line":
|
|
11673
|
+
"line": 135
|
|
11674
11674
|
},
|
|
11675
11675
|
"name": "publicDirEntries",
|
|
11676
11676
|
"type": {
|
|
@@ -11693,7 +11693,7 @@
|
|
|
11693
11693
|
"immutable": true,
|
|
11694
11694
|
"locationInModule": {
|
|
11695
11695
|
"filename": "src/nextjs-distribution.ts",
|
|
11696
|
-
"line":
|
|
11696
|
+
"line": 107
|
|
11697
11697
|
},
|
|
11698
11698
|
"name": "assetPrefix",
|
|
11699
11699
|
"optional": true,
|
|
@@ -11711,7 +11711,7 @@
|
|
|
11711
11711
|
"immutable": true,
|
|
11712
11712
|
"locationInModule": {
|
|
11713
11713
|
"filename": "src/nextjs-distribution.ts",
|
|
11714
|
-
"line":
|
|
11714
|
+
"line": 112
|
|
11715
11715
|
},
|
|
11716
11716
|
"name": "basePath",
|
|
11717
11717
|
"optional": true,
|
|
@@ -11728,7 +11728,7 @@
|
|
|
11728
11728
|
"immutable": true,
|
|
11729
11729
|
"locationInModule": {
|
|
11730
11730
|
"filename": "src/nextjs-distribution.ts",
|
|
11731
|
-
"line":
|
|
11731
|
+
"line": 116
|
|
11732
11732
|
},
|
|
11733
11733
|
"name": "certificate",
|
|
11734
11734
|
"optional": true,
|
|
@@ -11744,7 +11744,7 @@
|
|
|
11744
11744
|
"immutable": true,
|
|
11745
11745
|
"locationInModule": {
|
|
11746
11746
|
"filename": "src/nextjs-distribution.ts",
|
|
11747
|
-
"line":
|
|
11747
|
+
"line": 117
|
|
11748
11748
|
},
|
|
11749
11749
|
"name": "distribution",
|
|
11750
11750
|
"optional": true,
|
|
@@ -11762,7 +11762,7 @@
|
|
|
11762
11762
|
"immutable": true,
|
|
11763
11763
|
"locationInModule": {
|
|
11764
11764
|
"filename": "src/nextjs-distribution.ts",
|
|
11765
|
-
"line":
|
|
11765
|
+
"line": 148
|
|
11766
11766
|
},
|
|
11767
11767
|
"name": "functionGroupBehaviors",
|
|
11768
11768
|
"optional": true,
|
|
@@ -11785,7 +11785,7 @@
|
|
|
11785
11785
|
"immutable": true,
|
|
11786
11786
|
"locationInModule": {
|
|
11787
11787
|
"filename": "src/nextjs-distribution.ts",
|
|
11788
|
-
"line":
|
|
11788
|
+
"line": 141
|
|
11789
11789
|
},
|
|
11790
11790
|
"name": "functionGroups",
|
|
11791
11791
|
"optional": true,
|
|
@@ -11807,7 +11807,7 @@
|
|
|
11807
11807
|
"immutable": true,
|
|
11808
11808
|
"locationInModule": {
|
|
11809
11809
|
"filename": "src/nextjs-distribution.ts",
|
|
11810
|
-
"line":
|
|
11810
|
+
"line": 121
|
|
11811
11811
|
},
|
|
11812
11812
|
"name": "functionUrl",
|
|
11813
11813
|
"optional": true,
|
|
@@ -11824,7 +11824,7 @@
|
|
|
11824
11824
|
"immutable": true,
|
|
11825
11825
|
"locationInModule": {
|
|
11826
11826
|
"filename": "src/nextjs-distribution.ts",
|
|
11827
|
-
"line":
|
|
11827
|
+
"line": 125
|
|
11828
11828
|
},
|
|
11829
11829
|
"name": "loadBalancer",
|
|
11830
11830
|
"optional": true,
|
|
@@ -11844,7 +11844,7 @@
|
|
|
11844
11844
|
"immutable": true,
|
|
11845
11845
|
"locationInModule": {
|
|
11846
11846
|
"filename": "src/nextjs-distribution.ts",
|
|
11847
|
-
"line":
|
|
11847
|
+
"line": 160
|
|
11848
11848
|
},
|
|
11849
11849
|
"name": "maxCacheBehaviors",
|
|
11850
11850
|
"optional": true,
|
|
@@ -11861,13 +11861,53 @@
|
|
|
11861
11861
|
"immutable": true,
|
|
11862
11862
|
"locationInModule": {
|
|
11863
11863
|
"filename": "src/nextjs-distribution.ts",
|
|
11864
|
-
"line":
|
|
11864
|
+
"line": 130
|
|
11865
11865
|
},
|
|
11866
11866
|
"name": "overrides",
|
|
11867
11867
|
"optional": true,
|
|
11868
11868
|
"type": {
|
|
11869
11869
|
"fqn": "cdk-nextjs.NextjsDistributionOverrides"
|
|
11870
11870
|
}
|
|
11871
|
+
},
|
|
11872
|
+
{
|
|
11873
|
+
"abstract": true,
|
|
11874
|
+
"docs": {
|
|
11875
|
+
"default": "- none",
|
|
11876
|
+
"remarks": "It must define `viewerRequest(event)` (a function, sync or async, or a\n`var`/`let`/`const`): return a response to answer the viewer, or the\nrequest (or nothing) to carry on. It is spliced into cdk-nextjs's own\nviewer-request functions, ahead of their logic, so it may not use the\nname `handler`, and the combined function must fit CloudFront's 10 KB.\nIt runs on `cloudfront-js-2.0`, so it may be async and read\n{@link viewerRequestKeyValueStore} with `cf.kvs()`. A bring-your-own\n{@link distribution}'s default behavior isn't covered.",
|
|
11877
|
+
"see": "https://github.com/cdklabs/cdk-nextjs#running-code-on-every-viewer-request",
|
|
11878
|
+
"stability": "stable",
|
|
11879
|
+
"summary": "CloudFront Function code run first on every viewer request, on every behavior cdk-nextjs adds, static assets included — HTTP Basic auth on a pre-launch site, geo-gating."
|
|
11880
|
+
},
|
|
11881
|
+
"immutable": true,
|
|
11882
|
+
"locationInModule": {
|
|
11883
|
+
"filename": "src/nextjs-distribution.ts",
|
|
11884
|
+
"line": 178
|
|
11885
|
+
},
|
|
11886
|
+
"name": "viewerRequestFunctionCode",
|
|
11887
|
+
"optional": true,
|
|
11888
|
+
"type": {
|
|
11889
|
+
"fqn": "aws-cdk-lib.aws_cloudfront.FunctionCode"
|
|
11890
|
+
}
|
|
11891
|
+
},
|
|
11892
|
+
{
|
|
11893
|
+
"abstract": true,
|
|
11894
|
+
"docs": {
|
|
11895
|
+
"default": "- none",
|
|
11896
|
+
"remarks": "Read it with `cf.kvs()`, no ID needed.",
|
|
11897
|
+
"see": "https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/functions-custom-methods.html",
|
|
11898
|
+
"stability": "stable",
|
|
11899
|
+
"summary": "A CloudFront KeyValueStore associated with every viewer-request function {@link viewerRequestFunctionCode} is copied into (up to three, one per kind of behavior), so values it reads — Basic auth credentials, an allowlist — live outside the CloudFormation template and change without a deploy."
|
|
11900
|
+
},
|
|
11901
|
+
"immutable": true,
|
|
11902
|
+
"locationInModule": {
|
|
11903
|
+
"filename": "src/nextjs-distribution.ts",
|
|
11904
|
+
"line": 188
|
|
11905
|
+
},
|
|
11906
|
+
"name": "viewerRequestKeyValueStore",
|
|
11907
|
+
"optional": true,
|
|
11908
|
+
"type": {
|
|
11909
|
+
"fqn": "aws-cdk-lib.aws_cloudfront.IKeyValueStore"
|
|
11910
|
+
}
|
|
11871
11911
|
}
|
|
11872
11912
|
],
|
|
11873
11913
|
"symbolId": "src/nextjs-distribution:NextjsDistributionProps"
|
|
@@ -12423,7 +12463,7 @@
|
|
|
12423
12463
|
},
|
|
12424
12464
|
"locationInModule": {
|
|
12425
12465
|
"filename": "src/root-constructs/nextjs-global-containers.ts",
|
|
12426
|
-
"line":
|
|
12466
|
+
"line": 125
|
|
12427
12467
|
},
|
|
12428
12468
|
"parameters": [
|
|
12429
12469
|
{
|
|
@@ -12449,7 +12489,7 @@
|
|
|
12449
12489
|
"kind": "class",
|
|
12450
12490
|
"locationInModule": {
|
|
12451
12491
|
"filename": "src/root-constructs/nextjs-global-containers.ts",
|
|
12452
|
-
"line":
|
|
12492
|
+
"line": 107
|
|
12453
12493
|
},
|
|
12454
12494
|
"name": "NextjsGlobalContainers",
|
|
12455
12495
|
"properties": [
|
|
@@ -12461,7 +12501,7 @@
|
|
|
12461
12501
|
"immutable": true,
|
|
12462
12502
|
"locationInModule": {
|
|
12463
12503
|
"filename": "src/root-constructs/nextjs-global-containers.ts",
|
|
12464
|
-
"line":
|
|
12504
|
+
"line": 116
|
|
12465
12505
|
},
|
|
12466
12506
|
"name": "url",
|
|
12467
12507
|
"overrides": "cdk-nextjs.NextjsBaseConstruct",
|
|
@@ -12475,7 +12515,7 @@
|
|
|
12475
12515
|
},
|
|
12476
12516
|
"locationInModule": {
|
|
12477
12517
|
"filename": "src/root-constructs/nextjs-global-containers.ts",
|
|
12478
|
-
"line":
|
|
12518
|
+
"line": 108
|
|
12479
12519
|
},
|
|
12480
12520
|
"name": "nextjsContainers",
|
|
12481
12521
|
"type": {
|
|
@@ -12488,7 +12528,7 @@
|
|
|
12488
12528
|
},
|
|
12489
12529
|
"locationInModule": {
|
|
12490
12530
|
"filename": "src/root-constructs/nextjs-global-containers.ts",
|
|
12491
|
-
"line":
|
|
12531
|
+
"line": 109
|
|
12492
12532
|
},
|
|
12493
12533
|
"name": "nextjsDistribution",
|
|
12494
12534
|
"type": {
|
|
@@ -12501,7 +12541,7 @@
|
|
|
12501
12541
|
},
|
|
12502
12542
|
"locationInModule": {
|
|
12503
12543
|
"filename": "src/root-constructs/nextjs-global-containers.ts",
|
|
12504
|
-
"line":
|
|
12544
|
+
"line": 110
|
|
12505
12545
|
},
|
|
12506
12546
|
"name": "nextjsPostDeploy",
|
|
12507
12547
|
"type": {
|
|
@@ -12524,7 +12564,7 @@
|
|
|
12524
12564
|
"kind": "interface",
|
|
12525
12565
|
"locationInModule": {
|
|
12526
12566
|
"filename": "src/root-constructs/nextjs-global-containers.ts",
|
|
12527
|
-
"line":
|
|
12567
|
+
"line": 29
|
|
12528
12568
|
},
|
|
12529
12569
|
"name": "NextjsGlobalContainersConstructOverrides",
|
|
12530
12570
|
"properties": [
|
|
@@ -12536,7 +12576,7 @@
|
|
|
12536
12576
|
"immutable": true,
|
|
12537
12577
|
"locationInModule": {
|
|
12538
12578
|
"filename": "src/root-constructs/nextjs-global-containers.ts",
|
|
12539
|
-
"line":
|
|
12579
|
+
"line": 30
|
|
12540
12580
|
},
|
|
12541
12581
|
"name": "nextjsContainersProps",
|
|
12542
12582
|
"optional": true,
|
|
@@ -12552,7 +12592,7 @@
|
|
|
12552
12592
|
"immutable": true,
|
|
12553
12593
|
"locationInModule": {
|
|
12554
12594
|
"filename": "src/root-constructs/nextjs-global-containers.ts",
|
|
12555
|
-
"line":
|
|
12595
|
+
"line": 31
|
|
12556
12596
|
},
|
|
12557
12597
|
"name": "nextjsDistributionProps",
|
|
12558
12598
|
"optional": true,
|
|
@@ -12578,7 +12618,7 @@
|
|
|
12578
12618
|
"kind": "interface",
|
|
12579
12619
|
"locationInModule": {
|
|
12580
12620
|
"filename": "src/root-constructs/nextjs-global-containers.ts",
|
|
12581
|
-
"line":
|
|
12621
|
+
"line": 39
|
|
12582
12622
|
},
|
|
12583
12623
|
"name": "NextjsGlobalContainersOverrides",
|
|
12584
12624
|
"properties": [
|
|
@@ -12590,7 +12630,7 @@
|
|
|
12590
12630
|
"immutable": true,
|
|
12591
12631
|
"locationInModule": {
|
|
12592
12632
|
"filename": "src/root-constructs/nextjs-global-containers.ts",
|
|
12593
|
-
"line":
|
|
12633
|
+
"line": 41
|
|
12594
12634
|
},
|
|
12595
12635
|
"name": "nextjsContainers",
|
|
12596
12636
|
"optional": true,
|
|
@@ -12606,7 +12646,7 @@
|
|
|
12606
12646
|
"immutable": true,
|
|
12607
12647
|
"locationInModule": {
|
|
12608
12648
|
"filename": "src/root-constructs/nextjs-global-containers.ts",
|
|
12609
|
-
"line":
|
|
12649
|
+
"line": 42
|
|
12610
12650
|
},
|
|
12611
12651
|
"name": "nextjsDistribution",
|
|
12612
12652
|
"optional": true,
|
|
@@ -12622,7 +12662,7 @@
|
|
|
12622
12662
|
"immutable": true,
|
|
12623
12663
|
"locationInModule": {
|
|
12624
12664
|
"filename": "src/root-constructs/nextjs-global-containers.ts",
|
|
12625
|
-
"line":
|
|
12665
|
+
"line": 40
|
|
12626
12666
|
},
|
|
12627
12667
|
"name": "nextjsGlobalContainers",
|
|
12628
12668
|
"optional": true,
|
|
@@ -12646,7 +12686,7 @@
|
|
|
12646
12686
|
"kind": "interface",
|
|
12647
12687
|
"locationInModule": {
|
|
12648
12688
|
"filename": "src/root-constructs/nextjs-global-containers.ts",
|
|
12649
|
-
"line":
|
|
12689
|
+
"line": 45
|
|
12650
12690
|
},
|
|
12651
12691
|
"name": "NextjsGlobalContainersProps",
|
|
12652
12692
|
"properties": [
|
|
@@ -12661,7 +12701,7 @@
|
|
|
12661
12701
|
"immutable": true,
|
|
12662
12702
|
"locationInModule": {
|
|
12663
12703
|
"filename": "src/root-constructs/nextjs-global-containers.ts",
|
|
12664
|
-
"line":
|
|
12704
|
+
"line": 79
|
|
12665
12705
|
},
|
|
12666
12706
|
"name": "healthCheckPath",
|
|
12667
12707
|
"type": {
|
|
@@ -12678,7 +12718,7 @@
|
|
|
12678
12718
|
"immutable": true,
|
|
12679
12719
|
"locationInModule": {
|
|
12680
12720
|
"filename": "src/root-constructs/nextjs-global-containers.ts",
|
|
12681
|
-
"line":
|
|
12721
|
+
"line": 52
|
|
12682
12722
|
},
|
|
12683
12723
|
"name": "alb",
|
|
12684
12724
|
"optional": true,
|
|
@@ -12696,7 +12736,7 @@
|
|
|
12696
12736
|
"immutable": true,
|
|
12697
12737
|
"locationInModule": {
|
|
12698
12738
|
"filename": "src/root-constructs/nextjs-global-containers.ts",
|
|
12699
|
-
"line":
|
|
12739
|
+
"line": 57
|
|
12700
12740
|
},
|
|
12701
12741
|
"name": "distribution",
|
|
12702
12742
|
"optional": true,
|
|
@@ -12714,7 +12754,7 @@
|
|
|
12714
12754
|
"immutable": true,
|
|
12715
12755
|
"locationInModule": {
|
|
12716
12756
|
"filename": "src/root-constructs/nextjs-global-containers.ts",
|
|
12717
|
-
"line":
|
|
12757
|
+
"line": 62
|
|
12718
12758
|
},
|
|
12719
12759
|
"name": "ecsCluster",
|
|
12720
12760
|
"optional": true,
|
|
@@ -12731,13 +12771,52 @@
|
|
|
12731
12771
|
"immutable": true,
|
|
12732
12772
|
"locationInModule": {
|
|
12733
12773
|
"filename": "src/root-constructs/nextjs-global-containers.ts",
|
|
12734
|
-
"line":
|
|
12774
|
+
"line": 83
|
|
12735
12775
|
},
|
|
12736
12776
|
"name": "overrides",
|
|
12737
12777
|
"optional": true,
|
|
12738
12778
|
"type": {
|
|
12739
12779
|
"fqn": "cdk-nextjs.NextjsGlobalContainersOverrides"
|
|
12740
12780
|
}
|
|
12781
|
+
},
|
|
12782
|
+
{
|
|
12783
|
+
"abstract": true,
|
|
12784
|
+
"docs": {
|
|
12785
|
+
"default": "- none",
|
|
12786
|
+
"remarks": "It must define\n`viewerRequest(event)`, as a function or a `var`/`let`/`const`.",
|
|
12787
|
+
"see": "NextjsDistributionProps.viewerRequestFunctionCode *",
|
|
12788
|
+
"stability": "stable",
|
|
12789
|
+
"summary": "CloudFront Function code run first on every viewer request, static assets included — HTTP Basic auth on a pre-launch site, say."
|
|
12790
|
+
},
|
|
12791
|
+
"immutable": true,
|
|
12792
|
+
"locationInModule": {
|
|
12793
|
+
"filename": "src/root-constructs/nextjs-global-containers.ts",
|
|
12794
|
+
"line": 91
|
|
12795
|
+
},
|
|
12796
|
+
"name": "viewerRequestFunctionCode",
|
|
12797
|
+
"optional": true,
|
|
12798
|
+
"type": {
|
|
12799
|
+
"fqn": "aws-cdk-lib.aws_cloudfront.FunctionCode"
|
|
12800
|
+
}
|
|
12801
|
+
},
|
|
12802
|
+
{
|
|
12803
|
+
"abstract": true,
|
|
12804
|
+
"docs": {
|
|
12805
|
+
"default": "- none",
|
|
12806
|
+
"see": "NextjsDistributionProps.viewerRequestKeyValueStore *",
|
|
12807
|
+
"stability": "stable",
|
|
12808
|
+
"summary": "A CloudFront KeyValueStore `viewerRequestFunctionCode` can read with `cf.kvs()`, so credentials stay out of the template."
|
|
12809
|
+
},
|
|
12810
|
+
"immutable": true,
|
|
12811
|
+
"locationInModule": {
|
|
12812
|
+
"filename": "src/root-constructs/nextjs-global-containers.ts",
|
|
12813
|
+
"line": 98
|
|
12814
|
+
},
|
|
12815
|
+
"name": "viewerRequestKeyValueStore",
|
|
12816
|
+
"optional": true,
|
|
12817
|
+
"type": {
|
|
12818
|
+
"fqn": "aws-cdk-lib.aws_cloudfront.IKeyValueStore"
|
|
12819
|
+
}
|
|
12741
12820
|
}
|
|
12742
12821
|
],
|
|
12743
12822
|
"symbolId": "src/root-constructs/nextjs-global-containers:NextjsGlobalContainersProps"
|
|
@@ -12756,7 +12835,7 @@
|
|
|
12756
12835
|
},
|
|
12757
12836
|
"locationInModule": {
|
|
12758
12837
|
"filename": "src/root-constructs/nextjs-global-functions.ts",
|
|
12759
|
-
"line":
|
|
12838
|
+
"line": 111
|
|
12760
12839
|
},
|
|
12761
12840
|
"parameters": [
|
|
12762
12841
|
{
|
|
@@ -12782,7 +12861,7 @@
|
|
|
12782
12861
|
"kind": "class",
|
|
12783
12862
|
"locationInModule": {
|
|
12784
12863
|
"filename": "src/root-constructs/nextjs-global-functions.ts",
|
|
12785
|
-
"line":
|
|
12864
|
+
"line": 93
|
|
12786
12865
|
},
|
|
12787
12866
|
"name": "NextjsGlobalFunctions",
|
|
12788
12867
|
"properties": [
|
|
@@ -12794,7 +12873,7 @@
|
|
|
12794
12873
|
"immutable": true,
|
|
12795
12874
|
"locationInModule": {
|
|
12796
12875
|
"filename": "src/root-constructs/nextjs-global-functions.ts",
|
|
12797
|
-
"line":
|
|
12876
|
+
"line": 102
|
|
12798
12877
|
},
|
|
12799
12878
|
"name": "url",
|
|
12800
12879
|
"overrides": "cdk-nextjs.NextjsBaseConstruct",
|
|
@@ -12808,7 +12887,7 @@
|
|
|
12808
12887
|
},
|
|
12809
12888
|
"locationInModule": {
|
|
12810
12889
|
"filename": "src/root-constructs/nextjs-global-functions.ts",
|
|
12811
|
-
"line":
|
|
12890
|
+
"line": 95
|
|
12812
12891
|
},
|
|
12813
12892
|
"name": "nextjsDistribution",
|
|
12814
12893
|
"type": {
|
|
@@ -12821,7 +12900,7 @@
|
|
|
12821
12900
|
},
|
|
12822
12901
|
"locationInModule": {
|
|
12823
12902
|
"filename": "src/root-constructs/nextjs-global-functions.ts",
|
|
12824
|
-
"line":
|
|
12903
|
+
"line": 94
|
|
12825
12904
|
},
|
|
12826
12905
|
"name": "nextjsFunctions",
|
|
12827
12906
|
"type": {
|
|
@@ -12834,7 +12913,7 @@
|
|
|
12834
12913
|
},
|
|
12835
12914
|
"locationInModule": {
|
|
12836
12915
|
"filename": "src/root-constructs/nextjs-global-functions.ts",
|
|
12837
|
-
"line":
|
|
12916
|
+
"line": 96
|
|
12838
12917
|
},
|
|
12839
12918
|
"name": "nextjsPostDeploy",
|
|
12840
12919
|
"type": {
|
|
@@ -12857,7 +12936,7 @@
|
|
|
12857
12936
|
"kind": "interface",
|
|
12858
12937
|
"locationInModule": {
|
|
12859
12938
|
"filename": "src/root-constructs/nextjs-global-functions.ts",
|
|
12860
|
-
"line":
|
|
12939
|
+
"line": 32
|
|
12861
12940
|
},
|
|
12862
12941
|
"name": "NextjsGlobalFunctionsConstructOverrides",
|
|
12863
12942
|
"properties": [
|
|
@@ -12869,7 +12948,7 @@
|
|
|
12869
12948
|
"immutable": true,
|
|
12870
12949
|
"locationInModule": {
|
|
12871
12950
|
"filename": "src/root-constructs/nextjs-global-functions.ts",
|
|
12872
|
-
"line":
|
|
12951
|
+
"line": 33
|
|
12873
12952
|
},
|
|
12874
12953
|
"name": "nextjsDistributionProps",
|
|
12875
12954
|
"optional": true,
|
|
@@ -12895,7 +12974,7 @@
|
|
|
12895
12974
|
"kind": "interface",
|
|
12896
12975
|
"locationInModule": {
|
|
12897
12976
|
"filename": "src/root-constructs/nextjs-global-functions.ts",
|
|
12898
|
-
"line":
|
|
12977
|
+
"line": 41
|
|
12899
12978
|
},
|
|
12900
12979
|
"name": "NextjsGlobalFunctionsOverrides",
|
|
12901
12980
|
"properties": [
|
|
@@ -12907,7 +12986,7 @@
|
|
|
12907
12986
|
"immutable": true,
|
|
12908
12987
|
"locationInModule": {
|
|
12909
12988
|
"filename": "src/root-constructs/nextjs-global-functions.ts",
|
|
12910
|
-
"line":
|
|
12989
|
+
"line": 44
|
|
12911
12990
|
},
|
|
12912
12991
|
"name": "nextjsDistribution",
|
|
12913
12992
|
"optional": true,
|
|
@@ -12923,7 +13002,7 @@
|
|
|
12923
13002
|
"immutable": true,
|
|
12924
13003
|
"locationInModule": {
|
|
12925
13004
|
"filename": "src/root-constructs/nextjs-global-functions.ts",
|
|
12926
|
-
"line":
|
|
13005
|
+
"line": 43
|
|
12927
13006
|
},
|
|
12928
13007
|
"name": "nextjsFunctions",
|
|
12929
13008
|
"optional": true,
|
|
@@ -12939,7 +13018,7 @@
|
|
|
12939
13018
|
"immutable": true,
|
|
12940
13019
|
"locationInModule": {
|
|
12941
13020
|
"filename": "src/root-constructs/nextjs-global-functions.ts",
|
|
12942
|
-
"line":
|
|
13021
|
+
"line": 42
|
|
12943
13022
|
},
|
|
12944
13023
|
"name": "nextjsGlobalFunctions",
|
|
12945
13024
|
"optional": true,
|
|
@@ -12963,7 +13042,7 @@
|
|
|
12963
13042
|
"kind": "interface",
|
|
12964
13043
|
"locationInModule": {
|
|
12965
13044
|
"filename": "src/root-constructs/nextjs-global-functions.ts",
|
|
12966
|
-
"line":
|
|
13045
|
+
"line": 47
|
|
12967
13046
|
},
|
|
12968
13047
|
"name": "NextjsGlobalFunctionsProps",
|
|
12969
13048
|
"properties": [
|
|
@@ -12977,7 +13056,7 @@
|
|
|
12977
13056
|
"immutable": true,
|
|
12978
13057
|
"locationInModule": {
|
|
12979
13058
|
"filename": "src/root-constructs/nextjs-global-functions.ts",
|
|
12980
|
-
"line":
|
|
13059
|
+
"line": 52
|
|
12981
13060
|
},
|
|
12982
13061
|
"name": "distribution",
|
|
12983
13062
|
"optional": true,
|
|
@@ -12997,7 +13076,7 @@
|
|
|
12997
13076
|
"immutable": true,
|
|
12998
13077
|
"locationInModule": {
|
|
12999
13078
|
"filename": "src/root-constructs/nextjs-global-functions.ts",
|
|
13000
|
-
"line":
|
|
13079
|
+
"line": 65
|
|
13001
13080
|
},
|
|
13002
13081
|
"name": "functionGroups",
|
|
13003
13082
|
"optional": true,
|
|
@@ -13019,13 +13098,52 @@
|
|
|
13019
13098
|
"immutable": true,
|
|
13020
13099
|
"locationInModule": {
|
|
13021
13100
|
"filename": "src/root-constructs/nextjs-global-functions.ts",
|
|
13022
|
-
"line":
|
|
13101
|
+
"line": 69
|
|
13023
13102
|
},
|
|
13024
13103
|
"name": "overrides",
|
|
13025
13104
|
"optional": true,
|
|
13026
13105
|
"type": {
|
|
13027
13106
|
"fqn": "cdk-nextjs.NextjsGlobalFunctionsOverrides"
|
|
13028
13107
|
}
|
|
13108
|
+
},
|
|
13109
|
+
{
|
|
13110
|
+
"abstract": true,
|
|
13111
|
+
"docs": {
|
|
13112
|
+
"default": "- none",
|
|
13113
|
+
"remarks": "It must define\n`viewerRequest(event)`, as a function or a `var`/`let`/`const`.",
|
|
13114
|
+
"see": "NextjsDistributionProps.viewerRequestFunctionCode *",
|
|
13115
|
+
"stability": "stable",
|
|
13116
|
+
"summary": "CloudFront Function code run first on every viewer request, static assets included — HTTP Basic auth on a pre-launch site, say."
|
|
13117
|
+
},
|
|
13118
|
+
"immutable": true,
|
|
13119
|
+
"locationInModule": {
|
|
13120
|
+
"filename": "src/root-constructs/nextjs-global-functions.ts",
|
|
13121
|
+
"line": 77
|
|
13122
|
+
},
|
|
13123
|
+
"name": "viewerRequestFunctionCode",
|
|
13124
|
+
"optional": true,
|
|
13125
|
+
"type": {
|
|
13126
|
+
"fqn": "aws-cdk-lib.aws_cloudfront.FunctionCode"
|
|
13127
|
+
}
|
|
13128
|
+
},
|
|
13129
|
+
{
|
|
13130
|
+
"abstract": true,
|
|
13131
|
+
"docs": {
|
|
13132
|
+
"default": "- none",
|
|
13133
|
+
"see": "NextjsDistributionProps.viewerRequestKeyValueStore *",
|
|
13134
|
+
"stability": "stable",
|
|
13135
|
+
"summary": "A CloudFront KeyValueStore `viewerRequestFunctionCode` can read with `cf.kvs()`, so credentials stay out of the template."
|
|
13136
|
+
},
|
|
13137
|
+
"immutable": true,
|
|
13138
|
+
"locationInModule": {
|
|
13139
|
+
"filename": "src/root-constructs/nextjs-global-functions.ts",
|
|
13140
|
+
"line": 84
|
|
13141
|
+
},
|
|
13142
|
+
"name": "viewerRequestKeyValueStore",
|
|
13143
|
+
"optional": true,
|
|
13144
|
+
"type": {
|
|
13145
|
+
"fqn": "aws-cdk-lib.aws_cloudfront.IKeyValueStore"
|
|
13146
|
+
}
|
|
13029
13147
|
}
|
|
13030
13148
|
],
|
|
13031
13149
|
"symbolId": "src/root-constructs/nextjs-global-functions:NextjsGlobalFunctionsProps"
|
|
@@ -18558,7 +18676,7 @@
|
|
|
18558
18676
|
"immutable": true,
|
|
18559
18677
|
"locationInModule": {
|
|
18560
18678
|
"filename": "src/generated-structs/OptionalNextjsDistributionProps.ts",
|
|
18561
|
-
"line":
|
|
18679
|
+
"line": 87
|
|
18562
18680
|
},
|
|
18563
18681
|
"name": "assetPrefix",
|
|
18564
18682
|
"optional": true,
|
|
@@ -18576,7 +18694,7 @@
|
|
|
18576
18694
|
"immutable": true,
|
|
18577
18695
|
"locationInModule": {
|
|
18578
18696
|
"filename": "src/generated-structs/OptionalNextjsDistributionProps.ts",
|
|
18579
|
-
"line":
|
|
18697
|
+
"line": 102
|
|
18580
18698
|
},
|
|
18581
18699
|
"name": "assetsBucket",
|
|
18582
18700
|
"optional": true,
|
|
@@ -18594,7 +18712,7 @@
|
|
|
18594
18712
|
"immutable": true,
|
|
18595
18713
|
"locationInModule": {
|
|
18596
18714
|
"filename": "src/generated-structs/OptionalNextjsDistributionProps.ts",
|
|
18597
|
-
"line":
|
|
18715
|
+
"line": 67
|
|
18598
18716
|
},
|
|
18599
18717
|
"name": "basePath",
|
|
18600
18718
|
"optional": true,
|
|
@@ -18611,7 +18729,7 @@
|
|
|
18611
18729
|
"immutable": true,
|
|
18612
18730
|
"locationInModule": {
|
|
18613
18731
|
"filename": "src/generated-structs/OptionalNextjsDistributionProps.ts",
|
|
18614
|
-
"line":
|
|
18732
|
+
"line": 60
|
|
18615
18733
|
},
|
|
18616
18734
|
"name": "certificate",
|
|
18617
18735
|
"optional": true,
|
|
@@ -18627,7 +18745,7 @@
|
|
|
18627
18745
|
"immutable": true,
|
|
18628
18746
|
"locationInModule": {
|
|
18629
18747
|
"filename": "src/generated-structs/OptionalNextjsDistributionProps.ts",
|
|
18630
|
-
"line":
|
|
18748
|
+
"line": 55
|
|
18631
18749
|
},
|
|
18632
18750
|
"name": "distribution",
|
|
18633
18751
|
"optional": true,
|
|
@@ -18644,7 +18762,7 @@
|
|
|
18644
18762
|
"immutable": true,
|
|
18645
18763
|
"locationInModule": {
|
|
18646
18764
|
"filename": "src/generated-structs/OptionalNextjsDistributionProps.ts",
|
|
18647
|
-
"line":
|
|
18765
|
+
"line": 51
|
|
18648
18766
|
},
|
|
18649
18767
|
"name": "functionUrl",
|
|
18650
18768
|
"optional": true,
|
|
@@ -18661,7 +18779,7 @@
|
|
|
18661
18779
|
"immutable": true,
|
|
18662
18780
|
"locationInModule": {
|
|
18663
18781
|
"filename": "src/generated-structs/OptionalNextjsDistributionProps.ts",
|
|
18664
|
-
"line":
|
|
18782
|
+
"line": 46
|
|
18665
18783
|
},
|
|
18666
18784
|
"name": "loadBalancer",
|
|
18667
18785
|
"optional": true,
|
|
@@ -18680,7 +18798,7 @@
|
|
|
18680
18798
|
"immutable": true,
|
|
18681
18799
|
"locationInModule": {
|
|
18682
18800
|
"filename": "src/generated-structs/OptionalNextjsDistributionProps.ts",
|
|
18683
|
-
"line":
|
|
18801
|
+
"line": 41
|
|
18684
18802
|
},
|
|
18685
18803
|
"name": "maxCacheBehaviors",
|
|
18686
18804
|
"optional": true,
|
|
@@ -18696,7 +18814,7 @@
|
|
|
18696
18814
|
"immutable": true,
|
|
18697
18815
|
"locationInModule": {
|
|
18698
18816
|
"filename": "src/generated-structs/OptionalNextjsDistributionProps.ts",
|
|
18699
|
-
"line":
|
|
18817
|
+
"line": 96
|
|
18700
18818
|
},
|
|
18701
18819
|
"name": "nextjsType",
|
|
18702
18820
|
"optional": true,
|
|
@@ -18713,7 +18831,7 @@
|
|
|
18713
18831
|
"immutable": true,
|
|
18714
18832
|
"locationInModule": {
|
|
18715
18833
|
"filename": "src/generated-structs/OptionalNextjsDistributionProps.ts",
|
|
18716
|
-
"line":
|
|
18834
|
+
"line": 92
|
|
18717
18835
|
},
|
|
18718
18836
|
"name": "publicDirEntries",
|
|
18719
18837
|
"optional": true,
|
|
@@ -18725,6 +18843,44 @@
|
|
|
18725
18843
|
"kind": "array"
|
|
18726
18844
|
}
|
|
18727
18845
|
}
|
|
18846
|
+
},
|
|
18847
|
+
{
|
|
18848
|
+
"abstract": true,
|
|
18849
|
+
"docs": {
|
|
18850
|
+
"default": "- none",
|
|
18851
|
+
"remarks": "It must define `viewerRequest(event)` (a function, sync or async, or a\n`var`/`let`/`const`): return a response to answer the viewer, or the\nrequest (or nothing) to carry on. It is spliced into cdk-nextjs's own\nviewer-request functions, ahead of their logic, so it may not use the\nname `handler`, and the combined function must fit CloudFront's 10 KB.\nIt runs on `cloudfront-js-2.0`, so it may be async and read\n{@link viewerRequestKeyValueStore} with `cf.kvs()`. A bring-your-own\n{@link distribution}'s default behavior isn't covered.",
|
|
18852
|
+
"stability": "stable",
|
|
18853
|
+
"summary": "CloudFront Function code run first on every viewer request, on every behavior cdk-nextjs adds, static assets included — HTTP Basic auth on a pre-launch site, geo-gating."
|
|
18854
|
+
},
|
|
18855
|
+
"immutable": true,
|
|
18856
|
+
"locationInModule": {
|
|
18857
|
+
"filename": "src/generated-structs/OptionalNextjsDistributionProps.ts",
|
|
18858
|
+
"line": 29
|
|
18859
|
+
},
|
|
18860
|
+
"name": "viewerRequestFunctionCode",
|
|
18861
|
+
"optional": true,
|
|
18862
|
+
"type": {
|
|
18863
|
+
"fqn": "aws-cdk-lib.aws_cloudfront.FunctionCode"
|
|
18864
|
+
}
|
|
18865
|
+
},
|
|
18866
|
+
{
|
|
18867
|
+
"abstract": true,
|
|
18868
|
+
"docs": {
|
|
18869
|
+
"default": "- none",
|
|
18870
|
+
"remarks": "Read it with `cf.kvs()`, no ID needed.",
|
|
18871
|
+
"stability": "stable",
|
|
18872
|
+
"summary": "A CloudFront KeyValueStore associated with every viewer-request function {@link viewerRequestFunctionCode} is copied into (up to three, one per kind of behavior), so values it reads — Basic auth credentials, an allowlist — live outside the CloudFormation template and change without a deploy."
|
|
18873
|
+
},
|
|
18874
|
+
"immutable": true,
|
|
18875
|
+
"locationInModule": {
|
|
18876
|
+
"filename": "src/generated-structs/OptionalNextjsDistributionProps.ts",
|
|
18877
|
+
"line": 15
|
|
18878
|
+
},
|
|
18879
|
+
"name": "viewerRequestKeyValueStore",
|
|
18880
|
+
"optional": true,
|
|
18881
|
+
"type": {
|
|
18882
|
+
"fqn": "aws-cdk-lib.aws_cloudfront.IKeyValueStore"
|
|
18883
|
+
}
|
|
18728
18884
|
}
|
|
18729
18885
|
],
|
|
18730
18886
|
"symbolId": "src/generated-structs/OptionalNextjsDistributionProps:OptionalNextjsDistributionProps"
|
|
@@ -19929,6 +20085,6 @@
|
|
|
19929
20085
|
"symbolId": "src/nextjs-build/nextjs-build:PublicDirEntry"
|
|
19930
20086
|
}
|
|
19931
20087
|
},
|
|
19932
|
-
"version": "0.7.
|
|
19933
|
-
"fingerprint": "
|
|
20088
|
+
"version": "0.7.13",
|
|
20089
|
+
"fingerprint": "6ATOojt9o1v/PGHf4L8nYMKFUDATsQfbiMHtqZRzNxg="
|
|
19934
20090
|
}
|