1# Cloudflare Website: Next.js
2
3Deploys a [Next.js](https://nextjs.org) app to Cloudflare Workers with
4`Cloudflare.Website.Nextjs` — the wrangler-free OpenNext pipeline from
5`@alchemy.run/frontend-frameworks/nextjs`. No `wrangler.toml` or OpenNext config
6is required: the integration runs `next build` through `@opennextjs/cloudflare`, bundles
7the resulting worker, and deploys the static assets (including
8prerendered pages) alongside it.
9
10- `app/page.jsx` is server-rendered in the Worker on every request and
11 reads the `GREETING` binding declared in `alchemy.run.ts` via
12 OpenNext's `getCloudflareContext()`.
13- `app/api/hello/route.js` is an app-router API route handler.
14- Everything under `public/` deploys as static assets.
15- Without a native OpenNext config, Alchemy generates temporary read-only
16 static-assets defaults. For writable incremental static regeneration, pass
17 KV namespaces through `isr`; Alchemy binds them and the revalidation queue
18 and selects matching KV adapters.
19
20The integration packages must be installed in the project (the source
21provider is loaded dynamically at deploy time):
22
23```sh
24bun add -d @alchemy.run/frontend-frameworks @opennextjs/cloudflare
25```
26
27## Optional native OpenNext configuration
28
29The same minimal resource works with or without a config file:
30
31```typescript
32const site = yield* Cloudflare.Website.Nextjs("Site");
33```
34
35Without `open-next.config.ts`, Alchemy uses the temporary defaults described
36above; no config file is required. If the file exists under `rootDir` (the
37working directory by default), Alchemy loads it through OpenNext's native
38compiler and never rewrites it. Native Next.js and Tailwind configs are unchanged.
39
40For example, to keep read-only static-assets caching with a custom build command:
41
42```typescript
43// open-next.config.ts
44import { defineCloudflareConfig, type OpenNextConfig } from "@opennextjs/cloudflare";
45import staticAssetsIncrementalCache from "@opennextjs/cloudflare/overrides/incremental-cache/static-assets-incremental-cache";
46
47export default {
48 ...defineCloudflareConfig({ incrementalCache: staticAssetsIncrementalCache }),
49 buildCommand: "pnpm exec next build",
50} satisfies OpenNextConfig;
51```
52
53The full native `OpenNextConfig` shape, imports, and callbacks are preserved,
54subject to Cloudflare's adapter constraints; AWS-specific runtime features do
55not become available on Workers. An explicit resource `openNext.buildCommand`
56overrides the file's command. `openNext.minify` and `openNext.debug` remain
57resource-level build controls.
58
59With a native config, `isr` still binds the KV namespaces and Durable Object
60queue, but does not select adapters for you. Choose `kv-incremental-cache`,
61`kv-next-tag-cache`, and `do-queue` in the config to match those bindings.
62The static-assets example above is read-only.
63
64## Deploy
65
66```sh
67bun run deploy
68```
69
70Unchanged sources skip the OpenNext build entirely on subsequent
71deploys — the input files are content-hashed (scoped by `memo.include`).
72`open-next.config.ts` itself is always hashed. When narrowing `memo.include`,
73include any helpers imported by the config too.
74
75## Dev
76
77```sh
78bun run dev
79```
80
81Local development defaults to the production build served under workerd.
82Set `dev: { mode: "hmr" }` on the resource to run `next dev` with hot module
83replacement and Worker bindings proxied into `getCloudflareContext()`.
84
85## Destroy
86
87```sh
88bun run destroy
89```