1---
2title: Websites
3description: Deploy Vite, Astro, Next.js, vinext, Nuxt, React Router, SolidStart, SvelteKit, TanStack Start, Waku, Octane, Foldkit, Vocs, or any static build to Hetzner with first-class Website resources.
4sidebar:
5 label: Overview
6 order: 1
7---
8
9Alchemy deploys frontends to Hetzner with a family of
10`Hetzner.Website` resources. Each one builds your project
11programmatically and deploys it as a systemd
12[Service](/hetzner/compute/services) on a
13[Server](/hetzner/compute/servers) — Node on port 3000, no
14Dockerfile, no unit file, no adapter in the framework config.
15Your framework's own config file (`vite.config.ts`,
16`astro.config.*`, `nuxt.config.ts`, ...) loads natively; Alchemy
17layers its Node server on top.
18
19Omit `server` and Alchemy creates a `cpx12` / `ubuntu-24.04`
20Server in `fsn1`. Pass `server` to put several sites (or a site
21plus an API) on one VM.
22
23The live URL is **`http://{ipv4}:3000`**. There is no TLS on the
24Service. `domain` requires an existing Hetzner DNS
25[`Zone`](/hetzner/networking/dns) and creates an A record;
26`url` becomes `http://{domain}:3000`.
27
28- [`Vite`](/hetzner/frontend/vite) — client-only Vite apps
29 (React, Vue, Solid SPAs, `index.html` multi-page sites); a
30 static-file unit serves the `vite build` output.
31- [`Astro`](/hetzner/frontend/astro) — Astro sites, server-rendered
32 on Node or fully static; your `astro.config.*` loads natively.
33- [`Nextjs`](/hetzner/frontend/nextjs) — Next.js as a long-running
34 Node process (`next build`, then `next({ dev: false })`). Not
35 OpenNext.
36- [`Vinext`](/hetzner/frontend/vinext) — vinext (Next.js API on Vite)
37 as a long-running Node process (`vinext build`, then
38 `startProdServer`). Not the Cloudflare Worker path.
39- [`Nuxt`](/hetzner/frontend/nuxt) — Nuxt apps through nitro's
40 Node server; your `nuxt.config.ts` loads natively. Do not set
41 `nitro.preset`.
42- [`ReactRouter`](/hetzner/frontend/react-router) — React Router
43 v7 in framework mode, built through your own `vite build`.
44- [`SolidStart`](/hetzner/frontend/solidstart) — SolidStart 2.x
45 SSR; Alchemy appends nitro's `node` preset to your `vite build`.
46- [`SvelteKit`](/hetzner/frontend/sveltekit) — SvelteKit SSR plus
47 prerendered assets; the Node adapter is injected. Do not set
48 `kit.adapter`.
49- [`TanStackStart`](/hetzner/frontend/tanstack-start) — TanStack
50 Start (React or Solid), built through your own `vite build`.
51- [`Waku`](/hetzner/frontend/waku) — Waku (React Server
52 Components) on Node, with SSG pages served extensionless.
53- [`Octane`](/hetzner/frontend/octane) — OctaneJS SSR. Alchemy wraps
54 native Node output; no hosting adapter is needed in `octane.config.ts`.
55- [`Foldkit`](/hetzner/frontend/foldkit) — client-only Foldkit
56 SPA; deep links fall back to `index.html`.
57- [`Vocs`](/hetzner/frontend/vocs) — prerendered Vocs docs;
58 extensionless pages (`/about` → `about/index.html`).
59- [`StaticSite`](/hetzner/frontend/static-site) — any build
60 command's output directory (Hugo, Zola, Eleventy).
61
62The return is `{ url, server, service }` — `server` and
63`service` are `undefined` under `alchemy dev`.
64
65Shared props: `rootDir`, `memo`, `env` (process environment on
66the unit — not Worker bindings), `dev`, `domain`, `zone`,
67`server`. Builds are memoized by content-hashing the input
68files — an unchanged project skips the build.
69
70## What's supported
71
72| Framework | Resource | Guide |
73| --- | --- | --- |
74| React / Vue / Solid SPA | `Vite` | [Vite](/hetzner/frontend/vite) |
75| TanStack Start (React & Solid) | `TanStackStart` | [TanStack Start](/hetzner/frontend/tanstack-start) |
76| React Router | `ReactRouter` | [React Router](/hetzner/frontend/react-router) |
77| SolidStart | `SolidStart` | [SolidStart](/hetzner/frontend/solidstart) |
78| Astro | `Astro` | [Astro](/hetzner/frontend/astro) |
79| Next.js | `Nextjs` | [Next.js](/hetzner/frontend/nextjs) |
80| vinext | `Vinext` | [vinext](/hetzner/frontend/vinext) |
81| Nuxt | `Nuxt` | [Nuxt](/hetzner/frontend/nuxt) |
82| SvelteKit | `SvelteKit` | [SvelteKit](/hetzner/frontend/sveltekit) |
83| Waku | `Waku` | [Waku](/hetzner/frontend/waku) |
84| OctaneJS | `Octane` | [Octane](/hetzner/frontend/octane) |
85| Foldkit | `Foldkit` | [Foldkit](/hetzner/frontend/foldkit) |
86| Vocs | `Vocs` | [Vocs](/hetzner/frontend/vocs) |
87| Zola, Hugo, or any static generator | `StaticSite` | [Static sites](/hetzner/frontend/static-site) |
88
89See
90[examples/hetzner-website-vite](https://github.com/alchemy-run/alchemy/tree/main/examples/hetzner-website-vite)
91for a Vite SPA sharing a Server with an API unit.
92
93## How to choose
94
95Use the resource named after your framework. `Astro`, `Nextjs`,
96`Nuxt`, `ReactRouter`, `SolidStart`, `SvelteKit`,
97`TanStackStart`, `Waku`, `Octane`, `Foldkit`, and `Vocs` each
98drive that framework's programmatic build and know its output
99layout, config surface, and dev server.
100
101Use `Vite` when the whole deployable output is static assets — a
102React, Vue, or Solid SPA, or an `index.html`-per-route multi-page
103app. SSR frameworks that wrap Vite (`Astro`, `SvelteKit`,
104`Octane`, …) have their own resources; `Vite` never starts a
105framework server module.
106
107Use `StaticSite` when the build is an arbitrary shell command
108that emits a directory of files.
109
110Pass one `Hetzner.Server` into several Website (and API)
111resources when they should share a VM.
112
113## Environment variables
114
115Top-level `env` is copied onto `process.env` before build and
116dev, and onto the systemd unit at deploy. Client inlining is
117whatever the framework already does (`VITE_*` for Vite). It is
118not Worker bindings and not AWS `server.environment`.
119
120```typescript
121const site = yield* Hetzner.Website.Vite("Web", {
122 server,
123 env: {
124 VITE_API_URL: api.url,
125 },
126});
127```
128
129Server code reads `process.env`.
130
131## Local development
132
133`alchemy dev` runs the framework's own dev server (native HMR)
134instead of deploying. `site.url` is the local address and no
135Server or Service is created. Wrap the site in
136`Alchemy.remote()` to deploy the live path even during dev.
137
138## Custom domain
139
140`domain` requires `zone` — an existing Hetzner DNS Zone. v1
141does not create a Zone. Alchemy adds an A
142[`RecordSet`](/hetzner/networking/dns) pointing at the Server's
143public IPv4. Passing `domain` without `zone` fails.
144
145```typescript
146const site = yield* Hetzner.Website.Astro("Web", {
147 server,
148 domain: "app.example.com",
149 zone,
150});
151```
152
153`url` is `http://app.example.com:3000`. The Service itself does
154not terminate TLS.
155
156## Where next
157
158- [The Vite resource](/hetzner/frontend/vite) — assets-only SPA,
159 `assets.notFoundHandling`, sharing a Server.
160- [The StaticSite resource](/hetzner/frontend/static-site) — build
161 commands, SPA/404 handling.
162- Framework guides:
163 [Astro](/hetzner/frontend/astro),
164 [Next.js](/hetzner/frontend/nextjs),
165 [Nuxt](/hetzner/frontend/nuxt),
166 [React Router](/hetzner/frontend/react-router),
167 [SolidStart](/hetzner/frontend/solidstart),
168 [SvelteKit](/hetzner/frontend/sveltekit),
169 [TanStack Start](/hetzner/frontend/tanstack-start),
170 [Waku](/hetzner/frontend/waku),
171 [Octane](/hetzner/frontend/octane),
172 [Foldkit](/hetzner/frontend/foldkit),
173 [Vocs](/hetzner/frontend/vocs).
174- [Servers](/hetzner/compute/servers) and
175 [Services](/hetzner/compute/services) — the VM and systemd
176 unit these resources deploy.
177- [Zones & records](/hetzner/networking/dns) — the Zone
178 `domain` attaches to.
179- [`Vite` reference](/providers/hetzner/website/vite),
180 [`Astro` reference](/providers/hetzner/website/astro),
181 [`StaticSite` reference](/providers/hetzner/website/staticsite).