1---
2title: Static sites
3description: Deploy any static build to Prisma Compute with Prisma.Website.StaticSite — a shell command, output directory, and Bun static-file server.
4sidebar:
5 order: 4
6---
7
8`Prisma.Website.StaticSite` runs a build command, packages its output,
9and deploys a static-file server on **Bun in Prisma Compute**. Use it
10for Hugo, Zola, Eleventy, or a custom pipeline. The output is uploaded
11as `tar.gz`; there is no Docker image or registry.
12
13Static sites still run on Compute. This resource does not publish files
14to a global CDN or remove the runtime. For Vite apps, prefer
15[`Prisma.Website.Vite`](/prisma/frontend/vite).
16
17## Declare the Website
18
19`command` and `outdir` are required:
20
21```typescript
22// alchemy.run.ts
23import * as Prisma from "alchemy/Prisma";
24
25export const Website = Prisma.Website.StaticSite("Website", {
26 command: "hugo --minify",
27 outdir: "public",
28});
29```
30
31Install the generator your command invokes. Unlike framework resources,
32`StaticSite` does not load a framework build integration from your app;
33it uses [`Command.Build`](/providers/command/build) and the shared
34static-file server.
35
36The command is memoized from input content. Use `memo: { include: [...] }`
37to narrow inputs or `memo: false` to rebuild every time. `shell` and
38`timeout` follow `Command.Build`; see [Memoization](/command/memoization).
39
40## Add it to the Stack
41
42```typescript
43// alchemy.run.ts
44import * as Alchemy from "alchemy";
45import * as Effect from "effect/Effect";
46
47export default Alchemy.Stack(
48 "MyStaticSite",
49 { providers: Prisma.providers(), state: Alchemy.localState() },
50 Effect.gen(function* () {
51 const site = yield* Website;
52 return { url: site.url };
53 }),
54);
55```
56
57Live deploy creates a database-less Prisma project if you omit `project`.
58Pass an existing project to share it with other apps. `site.url` is the
59Compute endpoint, or the HTTPS hostname when `domain` is supplied.
60
61## Building from a subdirectory
62
63`cwd` is the command's working directory; it defaults to `rootDir`, then
64`.`. `outdir` is relative to that directory:
65
66```typescript
67export const Website = Prisma.Website.StaticSite("Web", {
68 rootDir: "apps/web",
69 command: "npm run build",
70 outdir: "dist",
71});
72```
73
74Use a dedicated build directory, not the application root. Only the
75output files are packaged, not the whole source repository.
76
77## SPAs and 404 pages
78
79A client-side router needs the index page on an unmatched URL:
80
81```typescript
82export const App = Prisma.Website.StaticSite("App", {
83 command: "npm run build",
84 outdir: "dist",
85 assets: { notFoundHandling: "single-page-application" },
86});
87```
88
89This returns `index.html` with status 200. `spa: true` is the equivalent
90command-site shorthand.
91
92A static site can return a custom error page with status 404:
93
94```typescript
95export const Docs = Prisma.Website.StaticSite("Docs", {
96 command: "hugo --minify",
97 outdir: "public",
98 errorPage: "404.html",
99});
100```
101
102`errorPage` is relative to `outdir`; it is mutually exclusive with
103`spa: true`. For the conventional `404.html`,
104`assets: { notFoundHandling: "404-page" }` also works.
105
106## Add environment variables
107
108```diff lang="typescript"
109export const Website = Prisma.Website.StaticSite("Website", {
110 command: "hugo --minify",
111 outdir: "public",
112+ env: { HUGO_ENV: "production" },
113});
114```
115
116`env` is passed to the build and Compute. Generators may embed values
117in their output; `Redacted` protects display, not generated public files.
118The hosted process is the static-file server, not a framework SSR handler.
119
120## Local development
121
122Supply the generator's native server to skip the production build:
123
124```typescript
125export const Website = Prisma.Website.StaticSite("Website", {
126 command: "hugo --minify",
127 outdir: "public",
128 dev: { command: "hugo server" },
129});
130```
131
132`dev.cwd` and `dev.env` override the command's directory and environment.
133The local URL is detected from stdout; set `dev.url` if the command does
134not print one.
135
136Without `dev.command`, Alchemy builds and serves `outdir` locally.
137Neither local path creates a Prisma project, database, app, or domain.
138Opt into live deployment during dev explicitly:
139
140```typescript
141export const Website = Prisma.Website.StaticSite("Website", {
142 command: "hugo --minify",
143 outdir: "public",
144}).pipe(Alchemy.remote());
145```
146
147## Custom domain
148
149```typescript
150export const Website = Prisma.Website.StaticSite("Website", {
151 command: "hugo --minify",
152 outdir: "public",
153 domain: "blog.example.com",
154});
155```
156
157`domain` creates `Prisma.CustomDomain` and changes `site.url` to the
158HTTPS hostname. The app must be on the project's current default branch.
159Configure its returned DNS records yourself and check status before
160cutover; see [Custom domains](/prisma/frontend/websites#custom-domains).
161
162## When to use a framework resource instead
163
164[Astro](/prisma/frontend/astro), [Foldkit](/prisma/frontend/foldkit),
165[Next.js](/prisma/frontend/nextjs), [Nuxt](/prisma/frontend/nuxt),
166[Octane](/prisma/frontend/octane), [React Router](/prisma/frontend/react-router),
167[SolidStart](/prisma/frontend/solidstart), [SvelteKit](/prisma/frontend/sveltekit),
168[TanStack Start](/prisma/frontend/tanstack-start), [Vite](/prisma/frontend/vite),
169[Vocs](/prisma/frontend/vocs), and [Waku](/prisma/frontend/waku) each know
170their own programmatic build and output layout. Use those instead of
171specifying `command` and `outdir` when your framework has a resource.
172
173## Where next
174
175- [StaticSite API](/providers/prisma/website/staticsite).
176- [Static-site example](https://github.com/alchemy-run/alchemy/tree/main/examples/prisma-website-static).
177- [Websites](/prisma/frontend/websites) and [Compute apps](/prisma/compute/apps).