1import {
2 frameworkSite,
3 staticConfigFromAssets,
4 type FrameworkSiteProps,
5} from "./FrameworkSite.ts";
6
7/** The framework-integration package that drives the Astro build. */
8export const ASTRO_FRAMEWORK_SPECIFIER =
9 "@alchemy.run/frontend-frameworks/astro";
10
11/** The Node container deploy target for the Astro build. */
12export const ASTRO_NODE_TARGET_SPECIFIER =
13 "@alchemy.run/frontend-frameworks/astro/node";
14
15export interface AstroProps extends FrameworkSiteProps {
16 /**
17 * Serializable Astro config merged OVER the project's own
18 * `astro.config.*` (which loads natively). `adapter` is owned by the Node
19 * deploy target and may not be set here.
20 */
21 astro?: {
22 /** The full URL the site deploys to (`Astro.site`). */
23 site?: string;
24 /** Base path the site deploys under. */
25 base?: string;
26 /**
27 * Astro output target. `"server"` renders pages on demand; individual
28 * pages opt into prerendering with `export const prerender = true`.
29 * `"static"` prerenders every page at build time and deploys
30 * assets-only (no SSR server).
31 * @default "server"
32 */
33 output?: "server" | "static";
34 /** Source directory, relative to `rootDir`. @default "./src" */
35 srcDir?: string;
36 /** Public (static passthrough) directory. @default "./public" */
37 publicDir?: string;
38 /** Build output directory. @default "./dist" */
39 outDir?: string;
40 /** Trailing-slash handling for routes. */
41 trailingSlash?: "always" | "never" | "ignore";
42 };
43}
44
45/**
46 * Deploy an [Astro](https://astro.build) application to Fly: a Service
47 * running the Node adapter's serve entry (static files first, then the
48 * framework handler) on port 3000.
49 *
50 * Pages render on demand by default (`output: "server"`). With
51 * `astro: { output: "static" }` every page is prerendered and the deploy
52 * is assets-only.
53 *
54 *
55 * ### Creating Astro Sites
56 * **Example:** Basic Astro App
57 * ```typescript
58 * const site = yield* Fly.Website.Astro("Web", {
59 * rootDir: "./app",
60 * });
61 * ```
62 *
63 * **Example:** Custom Domain
64 * ```typescript
65 * const site = yield* Fly.Website.Astro("Web", {
66 * rootDir: "./app",
67 * domain: "app.example.com",
68 * });
69 * ```
70 *
71 * ### Static Sites
72 * **Example:** Fully Static Astro Site
73 * ```typescript
74 * const site = yield* Fly.Website.Astro("Docs", {
75 * rootDir: "./docs",
76 * astro: { output: "static" },
77 * assets: { notFoundHandling: "404-page" },
78 * });
79 * ```
80 *
81 * @resource
82 * @product Website
83 */
84export const Astro = (id: string, props: AstroProps = {}) => {
85 const output = props.astro?.output ?? "server";
86 return frameworkSite(id, props, {
87 name: "Astro",
88 framework: ASTRO_FRAMEWORK_SPECIFIER,
89 target: ASTRO_NODE_TARGET_SPECIFIER,
90 options: { astro: { ...props.astro, output } },
91 static:
92 output === "static" ? staticConfigFromAssets(props.assets) : undefined,
93 });
94};