1import { frameworkSite, type FrameworkSiteProps } from "./FrameworkSite.ts";
2
3/** The framework-integration package that drives the React Router build. */
4export const REACT_ROUTER_FRAMEWORK_SPECIFIER =
5 "@alchemy.run/frontend-frameworks/react-router";
6
7/** The Node container deploy target for the React Router build. */
8export const REACT_ROUTER_NODE_TARGET_SPECIFIER =
9 "@alchemy.run/frontend-frameworks/react-router/node";
10
11export interface ReactRouterProps extends FrameworkSiteProps {}
12
13/**
14 * Deploy a [React Router](https://reactrouter.com) v7 app (framework mode)
15 * to Fly: the SSR server on a Machine, static assets baked into the image,
16 * served assets-first then the framework handler.
17 *
18 * The build runs through
19 * `@alchemy.run/frontend-frameworks/react-router` with the
20 * `@alchemy.run/frontend-frameworks/react-router/node` deploy target — both
21 * must be installed in your project, alongside `@react-router/dev`,
22 * `react-router`, and `vite`.
23 *
24 * Your `vite.config.ts` needs no adapter wiring. React Router's server
25 * build is a `ServerBuild` manifest rather than a request handler, so the
26 * integration wraps the manifest with `createRequestHandler` and packages
27 * the resulting fetch handler as a Node HTTP server on port 3000.
28 *
29 * React Server Components (React Router's `unstable` RSC plugin) and
30 * multi-environment builds are not supported yet — the build fails with an
31 * actionable error when more than one server entry is emitted.
32 *
33 *
34 * ### Creating React Router Sites
35 * **Example:** Basic React Router App
36 * ```typescript
37 * const site = yield* Fly.Website.ReactRouter("Web", {
38 * rootDir: "./app",
39 * });
40 * ```
41 *
42 * **Example:** Custom Domain
43 * ```typescript
44 * const site = yield* Fly.Website.ReactRouter("Web", {
45 * rootDir: "./app",
46 * domain: "app.example.com",
47 * });
48 * ```
49 *
50 * ### Server Configuration
51 * **Example:** Process Environment
52 * ```typescript
53 * const site = yield* Fly.Website.ReactRouter("Web", {
54 * rootDir: "./app",
55 * env: {
56 * GREETING: "Hello from React Router on Fly!",
57 * },
58 * });
59 * ```
60 *
61 * **Example:** Read An Environment Variable From A Loader
62 * ```typescript
63 * // app/routes/home.tsx
64 * export function loader() {
65 * return { greeting: process.env.GREETING ?? "Hello!" };
66 * }
67 * ```
68 *
69 * @resource
70 * @product Website
71 */
72export const ReactRouter = (id: string, props: ReactRouterProps = {}) =>
73 frameworkSite(id, props, {
74 name: "ReactRouter",
75 framework: REACT_ROUTER_FRAMEWORK_SPECIFIER,
76 target: REACT_ROUTER_NODE_TARGET_SPECIFIER,
77 });