| 1 | # AWS Website: Next.js |
| 2 | |
| 3 | Deploys a [Next.js](https://nextjs.org) app to AWS with |
| 4 | `AWS.Website.Nextjs` — the OpenNext (`@opennextjs/aws`) serverless |
| 5 | topology with zero CDK or CloudFormation wiring: the SSR server runs on |
| 6 | a streaming Lambda Function URL, static assets (including prerendered |
| 7 | pages) deploy to S3 behind CloudFront, images are optimized by a |
| 8 | dedicated Lambda at `/_next/image`, and ISR revalidation flows through |
| 9 | an SQS FIFO queue plus a DynamoDB tag-cache table. |
| 10 | |
| 11 | - `app/page.jsx` is server-rendered in the Lambda on every request and |
| 12 | reads the `GREETING` environment value declared in `alchemy.run.ts` |
| 13 | via `process.env`. |
| 14 | - `app/api/hello/route.ts` is an app-router API route handler. |
| 15 | - Everything under `public/` deploys as static assets. |
| 16 | |
| 17 | The integration packages must be installed in the project (the source |
| 18 | provider is loaded dynamically at deploy time): |
| 19 | |
| 20 | ```sh |
| 21 | bun add -d @alchemy.run/frontend-frameworks @opennextjs/aws |
| 22 | ``` |
| 23 | |
| 24 | `open-next.config.ts` is the minimal default the AWS deploy target |
| 25 | generates when a project has none: the server uses the |
| 26 | `aws-lambda-streaming` wrapper so the emitted handler streams on the |
| 27 | Function URL (`invokeMode: RESPONSE_STREAM`). |
| 28 | |
| 29 | > [!NOTE] |
| 30 | > Running this example from inside the alchemy monorepo hits a known |
| 31 | > OpenNext limitation: the repo's bun *isolated* installs store packages |
| 32 | > behind `node_modules/.bun` symlinks, and OpenNext's file trace ships |
| 33 | > the server's `node_modules` as symlinks that the Lambda zip flattens — |
| 34 | > breaking store-sibling resolution (`Cannot find module |
| 35 | > '@swc/helpers/...'` at runtime). A standalone copy of this project |
| 36 | > (plain `bun install`, hoisted `node_modules`) deploys and serves |
| 37 | > correctly. |
| 38 | |
| 39 | ## Deploy |
| 40 | |
| 41 | ```sh |
| 42 | bun run deploy |
| 43 | ``` |
| 44 | |
| 45 | Unchanged sources skip the OpenNext build entirely on subsequent |
| 46 | deploys — the input files are content-hashed (scoped by `memo.include`). |
| 47 | |
| 48 | ## Dev |
| 49 | |
| 50 | ```sh |
| 51 | bun run dev |
| 52 | ``` |
| 53 | |
| 54 | Local dev is Next's own dev server (`next dev`, native HMR) — no cloud |
| 55 | resources are created. |
| 56 | |
| 57 | ## Destroy |
| 58 | |
| 59 | ```sh |
| 60 | bun run destroy |
| 61 | ``` |