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 Fly 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 Service path.
23 *
24 *
25 * ### Creating Next.js Sites
26 * **Example:** Basic Next.js App
27 * ```typescript
28 * const site = yield* Fly.Website.Nextjs("Web", {
29 * rootDir: "./app",
30 * });
31 * ```
32 *
33 * **Example:** Custom Domain
34 * ```typescript
35 * const site = yield* Fly.Website.Nextjs("Web", {
36 * rootDir: "./app",
37 * domain: "app.example.com",
38 * });
39 * ```
40 *
41 * @resource
42 * @product Website
43 */
44export const Nextjs = (id: string, props: NextjsProps = {}) =>
45 frameworkSite(id, props, {
46 name: "Next.js",
47 framework: NEXTJS_NODE_FRAMEWORK_SPECIFIER,
48 target: NEXTJS_NODE_FRAMEWORK_SPECIFIER,
49 install: ["next", "react", "react-dom"],
50 skipClientAssets: true,
51 });