Nuxt
AWS.Website.Nuxt deploys a Nuxt app to AWS. It
builds the app through your project’s own @nuxt/kit with nitro’s
node preset: the nitro server runs on a
Lambda Web Function and streams its
responses, and client assets plus prerendered pages are served from a
private S3 bucket through CloudFront. A CloudFront Function routes each
request at the edge — uploaded files go to S3, everything else streams
from the server. There is no nitro.preset
to edit and no build command to run.
Install
Section titled “Install”The build integration is not bundled with alchemy. Install
@alchemy.run/frontend-frameworks; the resource loads its /nuxt and
/nuxt/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:a10573ebun add -d https://pkg.alchemy.run/@alchemy.run/frontend-frameworks/pr:2930:a10573enpm install -D https://pkg.alchemy.run/@alchemy.run/frontend-frameworks/pr:2930:a10573eyarn add -D https://pkg.alchemy.run/@alchemy.run/frontend-frameworks/pr:2930:a10573eConfigure Nuxt
Section titled “Configure Nuxt”Your nuxt.config.ts loads natively — modules, layers, and all —
so configure Nuxt exactly as you would outside Alchemy:
export default defineNuxtConfig({ modules: ["@nuxtjs/tailwindcss"], routeRules: { "/about": { prerender: true }, },});Don’t set nitro.preset — the deploy target owns the preset (node,
or aws-lambda with streaming enabled for server: "function"), and a
foreign preset is a hard error.
Deploy-time overrides
Section titled “Deploy-time overrides”Config that only exists at deploy time — a stage-dependent base URL, a
per-environment runtimeConfig — goes in the nuxt prop. It merges
over nuxt.config.ts as the highest-priority layer, so a value here
wins:
export const Website = AWS.Website.Nuxt("Website", { nuxt: { app: { baseURL: "/docs/" }, runtimeConfig: { public: { apiBase: "https://api.example.com" }, }, },});The bag must be JSON-serializable — no functions, plugins, or modules;
those belong in nuxt.config.ts. nitro.preset stays owned by the
deploy target.
Declare the Website
Section titled “Declare the Website”Declare the site as a module-level const (rather than inline in the Stack):
import * as AWS from "@alchemy.run/aws";
export const Website = AWS.Website.Nuxt("Website");Add it to the Stack
Section titled “Add it to the Stack”Yield the site from your Stack and return its URL:
import * as Alchemy from "alchemy";import * as Effect from "effect/Effect";
export default Alchemy.Stack( "MyNuxtSite", { providers: AWS.providers(), state: AWS.state(), }, Effect.gen(function* () { const site = yield* Website; return { url: site.url }; }),);See examples/aws-website-nuxt for the checked-in example.
Add environment variables
Section titled “Add environment variables”The server function’s environment is configured under env — plain
values, or outputs from other resources in the Stack:
export const Website = AWS.Website.Nuxt("Website", { env: { NUXT_PUBLIC_API_BASE: api.url, },});env values are set on the server on deploy and injected into
the dev server’s process environment under alchemy dev, so server
code reads the same values in both modes. Sibling props tune the
server itself (timeout, maxConcurrencyPerEnvironment,
maxEnvironments).
Read the environment in server code
Section titled “Read the environment in server code”On AWS the nitro server is a plain Node server, so server routes
and SSR read the environment from process.env — or, the more
idiomatic Nuxt way, through runtimeConfig overridden by
NUXT_-prefixed environment variables:
export default defineEventHandler(() => { return { greeting: process.env.GREETING ?? "hello" };});Prerendering
Section titled “Prerendering”Routes marked for prerendering in routeRules (or via
nitro.prerender) render at build time into .output/public and are
uploaded to S3, served from the edge with no Lambda invocation.
Configure them in your project’s nuxt.config.ts:
export default defineNuxtConfig({ routeRules: { "/about": { prerender: true }, },});Nitro’s isr route rule is implemented only by the Vercel and
Netlify presets. On AWS it is silently ignored at build time,
and the route renders on demand on the server like any other SSR
route. Use prerender for build-time static routes, or cache route
rules for runtime caching.
Run on a Lambda Function
Section titled “Run on a Lambda Function”Web Functions run in a subset of Regions. Elsewhere, set
server: "function": the app builds with nitro’s aws-lambda preset
(from the /nuxt/aws export) and runs on a Lambda Function behind a
streaming Function URL, tuned with memorySize, architecture, and
runtime:
export const Website = AWS.Website.Nuxt("Website", { server: "function", memorySize: 2048,});Local dev
Section titled “Local dev”pnpm alchemy devbun alchemy devnpx alchemy devyarn alchemy devalchemy dev runs Nuxt’s own dev server (nitro dev, full HMR)
instead of deploying anything; site.url is the dev server’s
http://localhost:<port> address and no AWS resources are created.
Wrap the site in Alchemy.remote() to deploy the real infrastructure
even during dev.
Custom domain
Section titled “Custom domain”const site = yield* AWS.Website.Nuxt("Web", { domain: { name: "app.example.com" },});The certificate is created in us-east-1 (required by CloudFront),
DNS validation records and the alias record are managed through
Route 53. The hosted zone is inferred from the hostname — pass
hostedZoneId to pin it when several zones could match.
Share a distribution with Router
Section titled “Share a distribution with Router”CloudFront distributions take minutes to create. To serve several
sites (or a site plus an API) from one distribution, attach the site
to an AWS.Website.Router:
const router = yield* AWS.Website.Router("FrontDoor", { domain: { name: "example.com" },});
const site = yield* AWS.Website.Nuxt("Web", { domain: { router },});