Octane
AWS.Website.Octane deploys an OctaneJS
fullstack app to AWS. Octane wraps Vite, so the resource is
deliberately thin: it runs your project’s own vite build — Octane’s
plugin builds the client bundle and the self-contained SSR server
bundle, and the deploy target’s finishing pass wraps its fetch handler
in a Node server. The server deploys on a
Lambda Web Function; dist/client is
served from a private S3 bucket
through CloudFront. No CloudFormation, 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 the package’s
/octane and /octane/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 Octane
Section titled “Configure Octane”Keep native compiler and route settings in octane.config.ts, without
an adapter:
import { defineConfig, RenderRoute } from "@octanejs/vite-plugin";
export default defineConfig({ router: { routes: [new RenderRoute({ path: "/", entry: ["App", "/src/App.tsx"] })], },});AWS.Website.Octane selects hosting and automatically wraps Octane’s
default native Node output in a Node server. The legacy AWS
marker adapter remains optional for existing projects.
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.Octane("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( "MyOctaneSite", { providers: AWS.providers(), state: AWS.state(), }, Effect.gen(function* () { const site = yield* Website; return { url: site.url }; }),);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.Octane("Website", { env: { GREETING: "Hello from alchemy", API_BASE: api.url, },});The values are set on the server at deploy time and injected into the
dev server’s process environment under alchemy dev, so server code
reads the same values in both modes.
Read the environment in server code
Section titled “Read the environment in server code”Octane’s server is a plain Node server, so middleware and
ServerRoute handlers read the environment from process.env:
new ServerRoute({ path: "/api/greeting", methods: ["GET"], handler: async () => { return Response.json({ greeting: process.env.GREETING ?? "hello" }); },});Asset routing
Section titled “Asset routing”Octane’s intended setup is asset-first with SSR on miss: exact files
in dist/client serve from S3 via the CloudFront edge router without
invoking the server, and every miss streams from Octane SSR on the
server. That is the default — there is nothing to configure.
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 the /octane/aws deploy target
and runs on a Lambda Function behind a streaming Function URL, tuned with
memorySize, architecture, and runtime:
export const Website = AWS.Website.Octane("Website", { server: "function", memorySize: 2048,});Local dev
Section titled “Local dev”pnpm alchemy devbun alchemy devnpx alchemy devyarn alchemy devalchemy dev runs Octane’s own Vite dev server — the plugin’s
in-process SSR middleware serves rendering, server routes, and RPC
with full HMR. site.url is the local 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.Octane("Web", { domain: { name: "app.example.com" },});The hosted zone is inferred from the hostname. Pass hostedZoneId to
pin it when several zones could match.