Astro
Archil.Website.Astro deploys a Astro app to an Archil
sandbox, server-rendered on Node by default; pages that export const prerender = true are served as static files. The site is the
program of its own sandbox, on port 3000, at a public
https://3000-…archil.app URL. A stopped sandbox starts again on the next
request.
Install
Section titled “Install”The build integration is not bundled with alchemy. Install
@alchemy.run/frontend-frameworks; the resource loads its /astro
and /astro/node exports from your project at deploy time. It is
only used at build time, so a dev dependency is enough:
pnpm add -D https://pkg.alchemy.run/@alchemy.run/frontend-frameworks/pr:2930:d8eb8a5bun add -d https://pkg.alchemy.run/@alchemy.run/frontend-frameworks/pr:2930:d8eb8a5npm install -D https://pkg.alchemy.run/@alchemy.run/frontend-frameworks/pr:2930:d8eb8a5yarn add -D https://pkg.alchemy.run/@alchemy.run/frontend-frameworks/pr:2930:d8eb8a5Configure Astro
Section titled “Configure Astro”Your astro.config.* file loads natively — integrations, Vite
plugins, and any other non-serializable options work exactly as they
do outside Alchemy. Alchemy merges a programmatic config over it:
the Node adapter is injected for you (don’t declare an adapter in
your config — that fails the build with an actionable error), and
options passed via the astro prop override the file’s — see
Astro configuration below for the details.
Declare the Website
Section titled “Declare the Website”Declare the site as a module-level const:
import * as Archil from "@alchemy.run/archil";
export const Website = Archil.Website.Astro("Website");sandbox sizes the site’s sandbox and sets its image, timeouts, disks and network policy:
export const Website = Archil.Website.Astro("Website", { sandbox: { vcpuCount: 2, memSizeMiB: 4096, idleTtlSeconds: 600 },});Add it to the Stack
Section titled “Add it to the Stack”Yield the site from your Stack and return its URL:
import * as Archil from "@alchemy.run/archil";import * as Alchemy from "alchemy";import * as Effect from "effect/Effect";
export const Website = Archil.Website.Astro("Website");
export default Alchemy.Stack( "MyAstroSite", { providers: Archil.providers(), state: Alchemy.localState(), }, Effect.gen(function* () { const site = yield* Website; return { url: site.url }; }),);Run alchemy deploy. url is the site’s https://3000-…archil.app URL.
site.sandbox is the sandbox behind it, and undefined under
alchemy dev.
See examples/archil-website-astro for the checked-in example.
Add environment variables
Section titled “Add environment variables”Process environment is the top-level env prop — plain strings, or
Redacted values. They are copied onto process.env before build
and alchemy dev, and onto the program at deploy:
export const Website = Archil.Website.Astro("Website", { env: { GREETING: "Hello from Alchemy!", API_BASE: "https://api.example.com", },});This is the hosted Node process, not Worker bindings.
Read the environment in server code
Section titled “Read the environment in server code”The Astro server runs in Node in the sandbox, so server-rendered
pages and endpoints read the environment from process.env:
---const greeting = process.env.GREETING ?? "hello";---
<h1>{greeting}</h1>Astro inlines PUBLIC_* keys at build time. Because env is
applied before the build, those keys behave the same as in a local
astro build.
Fully static sites
Section titled “Fully static sites”With astro: { output: "static" } every page is prerendered at
build time and the deploy is assets-only — no Astro handler, just a
static-file server as the program:
export const Website = Archil.Website.Astro("Website", { astro: { output: "static" }, assets: { notFoundHandling: "404-page" },});assets.notFoundHandling applies only to output: "static".
"404-page" serves the built 404.html for unmatched routes;
"single-page-application" answers misses with the index page
(200) instead.
Astro configuration
Section titled “Astro configuration”Your astro.config.* is the primary place to configure Astro —
integrations, Vite plugins, and every other option (serializable or
not) work as usual:
import { defineConfig } from "astro/config";import react from "@astrojs/react";import tailwindcss from "@tailwindcss/vite";
export default defineConfig({ site: "https://blog.example.com", integrations: [react()], vite: { plugins: [tailwindcss()], },});The astro prop on the resource exposes common serializable options
for deploy-specific overrides; Astro merges them over the config
file (scalars override, arrays like integrations and
vite.plugins concatenate after the file’s):
export const Website = Archil.Website.Astro("Website", { astro: { site: "https://preview.example.com", },});Two options are managed for you regardless of the config file:
adapter— Alchemy injects the Node adapter. Declaring an adapter inastro.config.*fails the build with an actionable error.output— Alchemy defaults it to"server"(superseding a file-leveloutput), so pages render on demand in the sandbox. Opt into a fully prerendered site withastro: { output: "static" }on the resource.
site, base, srcDir, publicDir, outDir, and
trailingSlash are the other serializable keys on astro.
Local dev
Section titled “Local dev”alchemy dev runs Astro’s own dev server (native HMR) instead of
deploying; site.url is the local address and no Archil resources
are created. Wrap the site in Alchemy.remote() to deploy the real
sandbox even during dev.
Where next
Section titled “Where next”Archil.Website.Astroreference- Websites — every framework Archil hosts
- Programs and Sandboxes — what the site runs on