Websites
Alchemy deploys frontends to Fly with a family of Fly.Website
resources. Each one builds your project programmatically and
deploys it as a Node Service on a Fly
App — a Machine listening on port 3000, plus
a shared IPv4 so https://{app}.fly.dev answers — with no
fly.toml and no adapter to put in the framework config. Your
framework’s own config file (vite.config.ts, astro.config.*,
nuxt.config.ts, …) loads natively; Alchemy layers its Node
container integration on top.
Vite— client-only Vite apps (React, Vue, Solid SPAs,index.htmlmulti-page sites); a tiny static-file server serves thevite buildoutput.Astro— Astro sites, server-rendered on Node or fully static; yourastro.config.*loads natively.Nextjs— Next.js as a long-running Node process (next build, thennext({ dev: false })). Not OpenNext.Nuxt— Nuxt apps through nitro’s Node server; yournuxt.config.tsloads natively. Do not setnitro.preset.ReactRouter— React Router v7 in framework mode, built through your ownvite build.SolidStart— SolidStart 2.x SSR; Alchemy appends nitro’snodepreset to yourvite build.SvelteKit— SvelteKit SSR plus prerendered assets; the Node adapter is injected. Do not setkit.adapter.TanStackStart— TanStack Start (React or Solid), built through your ownvite build.Waku— Waku (React Server Components) on Node, with SSG pages served extensionless.Octane— OctaneJS SSR. Selectnode()from@alchemy.run/frontend-frameworks/octane/node-adapterinoctane.config.ts.Foldkit— client-only Foldkit SPA; deep links fall back toindex.html.Vocs— prerendered Vocs docs; extensionless pages (/about→about/index.html).StaticSite— any build command’s output directory (Hugo, Zola, Eleventy).
Each resource creates a Fly.App when you omit app, a
Fly.Service on port 3000, and a shared_v4
IpAssignment so {app}.fly.dev answers.
domain requests ACME via Certificate
(existing DNS only for v1); url becomes https://{domain}.
The return is { url, app, service, ip, certificate } —
everything except url is undefined under alchemy dev.
Shared props: rootDir, memo, env (Machine process
environment — not Worker bindings), dev, domain, app.
Builds are memoized by content-hashing the input files — an
unchanged project skips the build.
What’s supported
Section titled “What’s supported”| Framework | Resource | Guide |
|---|---|---|
| React / Vue / Solid SPA | Vite |
Vite |
| TanStack Start (React & Solid) | TanStackStart |
TanStack Start |
| React Router | ReactRouter |
React Router |
| SolidStart | SolidStart |
SolidStart |
| Astro | Astro |
Astro |
| Next.js | Nextjs |
Next.js |
| Nuxt | Nuxt |
Nuxt |
| SvelteKit | SvelteKit |
SvelteKit |
| Waku | Waku |
Waku |
| OctaneJS | Octane |
Octane |
| Foldkit | Foldkit |
Foldkit |
| Vocs | Vocs |
Vocs |
| Zola, Hugo, or any static generator | StaticSite |
Static sites |
See examples/fly-website-vite for a Vite SPA next to a Fly Service API.
How to choose
Section titled “How to choose”Use the resource named after your framework. Astro, Nextjs,
Nuxt, ReactRouter, SolidStart, SvelteKit,
TanStackStart, Waku, Octane, Foldkit, and Vocs each
drive that framework’s programmatic build and know its output
layout, config surface, and dev server.
Use Vite when the whole deployable output is static assets — a
React, Vue, or Solid SPA, or an index.html-per-route multi-page
app. SSR frameworks that wrap Vite (Astro, SvelteKit,
Octane, …) have their own resources; Vite never starts a
framework server module.
Use StaticSite when the build is an arbitrary shell command
that emits a directory of files.
Environment variables
Section titled “Environment variables”Top-level env is copied onto process.env before build and
dev, and onto the Machine at deploy. Client inlining is whatever
the framework already does (VITE_* for Vite). It is not Worker
bindings and not AWS server.environment.
const site = yield* Fly.Website.Vite("Web", { env: { VITE_API_URL: api.url, },});Server code reads process.env. Pair a site with
Postgres the same way you would any other
Service: put the connection string in env, or bind
ConnectPostgres on a sibling Service.
Local development
Section titled “Local development”alchemy dev runs the framework’s own dev server (native HMR)
instead of deploying. site.url is the local address and no Fly
App, Service, IP, or certificate is created. Wrap the site in
Alchemy.remote() to deploy the live path even during dev.
Custom domain
Section titled “Custom domain”const site = yield* Fly.Website.Astro("Web", { domain: "app.example.com",});domain is a hostname string. Alchemy requests ACME on the App;
point existing DNS at the App first (v1 does not create records).
url becomes https://app.example.com.
Where next
Section titled “Where next”- The Vite resource — assets-only SPA,
assets.notFoundHandling, env inlining. - The StaticSite resource — build commands, SPA/404 handling.
- Framework guides: Astro, Next.js, Nuxt, React Router, SolidStart, SvelteKit, TanStack Start, Waku, Octane, Foldkit, Vocs.
- Services — the Node process these resources deploy.
- Postgres — managed Postgres next to a site.
Vitereference,Astroreference,StaticSitereference.