Deployment

An AFW app compiles to static files — a hashed JS bundle, CSS, and (optionally) pre-rendered HTML — so today you build once and serve dist/ from any static host or CDN, with no runtime to operate.

AFW is a fullstack framework. Alongside the static output, it can run a server: an app-owned server entry renders routes per request (SSR) and mounts your API routes at their file paths (route.{js,ts} works in any folder, conventionally app/api/). Typed server functions are still in progress.

Choose the output that fits your app:

  • Production Build — a single-page app: one index.html shell plus the bundle. The client renders every route. Best for app-like sites behind auth or with mostly dynamic content.

  • Static Generation — additionally prerenders routes to their own HTML files through an explicit build step. Best for content and marketing sites that need SEO and instant first paint.

  • Server — run a server for per-request SSR and API routes, through a server entry or runtime adapter. Best for fullstack apps that need server logic.

  • Fetch handler — deploy dist/server/api.js to any Fetch-native runtime (Workers, Deno, Bun edge, etc.): static assets plus middleware and API routes, with platform bindings via context.env.

Same bundle, more HTML

SSG doesn't change your app — it runs the same components through a string renderer at build time, then the client bundle adopts that markup on load (Hydration). You can start with a plain build and add a prerender target later.

Hosting

dist/ is self-contained static output. Point any of these at it:

  • A static host / CDN (Netlify, Vercel, Cloudflare Pages, GitHub Pages, S3 + CloudFront).

  • Any web server (nginx, Caddy) serving the folder.

For a single-page build, configure the host to fall back to index.html for unknown paths so client-side routes resolve. A fully static-generated site needs no fallback — generated routes have their own HTML files. Configure the host to return your 404 page for paths that were not generated.

Running a server

If your app uses SSR or API routes, run a server instead of serving dist/ statically — through your server entry or an explicitly emitted dist/server/api.js behind a runtime adapter (Bun, Node, Cloudflare Workers, Deno). See Server for the native entry and adapter options.

Last updated on
Edit this page