1import { frameworkSite, type FrameworkSiteProps } from "./FrameworkSite.ts";
2
3/**
4 * The Next.js-on-Node framework module (`next build` + a custom
5 * `next({ dev: false })` server). Not OpenNext.
6 */
7export const NEXTJS_NODE_FRAMEWORK_SPECIFIER =
8 "@alchemy.run/frontend-frameworks/nextjs/node";
9
10export interface NextjsProps extends FrameworkSiteProps {}
11
12/**
13 * Deploy a Next.js application to Cloud Run as a long-running Node process:
14 * `next build`, then a serve entry that `import("next")` +
15 * `next({ dev: false }).prepare()` + `getRequestHandler()`. The `.next`
16 * output (and `public/` when present) is baked into the image; `next` is
17 * installed unbundled.
18 *
19 * Do not use OpenNext AWS/CF wrappers — those are Lambda/workerd.
20 *
21 * During `alchemy dev` the site is `next dev` and no cloud resources are
22 * declared; `Alchemy.remote()` opts back into the live Cloud Run service.
23 *
24 *
25 * ### Creating Next.js Sites
26 * **Example:** Basic Next.js App
27 * ```typescript
28 * const site = yield* GCP.Website.Nextjs("Web", {
29 * rootDir: "./app",
30 * });
31 * ```
32 *
33 * **Example:** Warm Instance with More Memory
34 * ```typescript
35 * const site = yield* GCP.Website.Nextjs("Web", {
36 * rootDir: "./app",
37 * scaling: { minInstanceCount: 1 },
38 * resources: { limits: { cpu: "1", memory: "1Gi" } },
39 * });
40 * ```
41 *
42 * @resource
43 * @product Website
44 */
45export const Nextjs = (id: string, props: NextjsProps = {}) =>
46 frameworkSite(id, props, {
47 name: "Next.js",
48 framework: NEXTJS_NODE_FRAMEWORK_SPECIFIER,
49 target: NEXTJS_NODE_FRAMEWORK_SPECIFIER,
50 install: ["next", "react", "react-dom"],
51 skipClientAssets: true,
52 });