Rendering
Each route selects how HTML is produced via the render field on defineRoutes.
| Mode | When HTML is produced | Typical use |
|---|---|---|
ssr |
On each request | Dynamic, personalized, or frequently changing data |
ssg |
At avedon build |
Mostly static marketing or content pages |
csr |
In the browser | Highly interactive shells after a minimal boot |
Default when unspecified: ssr.
SSR
Server-side rendering runs load per request, then streams HTML that the client hydrates.
Default: SSR routes stream a ReadableStream body. The framework does not wait for the full page HTML before sending bytes unless you opt out with bufferHtml: true.
Streaming (default)
- Shell timing: avedon starts
load()and waits up to ~40ms before flushing the document shell (head + opening#app). Ifload()is still running after the window, the shell flushes early so TTFB stays low. - Sync template HTML streams next; slow work can follow in later chunks.
{#await}blocks emit a placeholder, then a late injection when the promise settles.__AVEDON_DATA__and the client entry are sent after await boundaries settle.
Use for request-dependent data, fresh pages, and slow {#await} regions where early bytes matter.
bufferHtml: true
When set on an SSR route, avedon waits for load() and the full HTML body, then sends one complete document. Use when:
<head>depends onload— title/meta must be correct in the first HTML snapshotload()often redirects or errors — you need real HTTP302/404/403without post-shell fallback- Streaming buys little on a fast route
Redirects and errors in load()
| When | Behavior |
|---|---|
load() finishes before the shell is committed |
Normal HTTP: redirect() → 302; notFound() / error() → matching status |
Shell already sent, then load() redirects |
Injects <script>window.location.href=…</script> (cannot change status) |
Shell already sent, then notFound() / error() |
Error UI streams into the body; HTTP status stays 200 |
Form actions (POST) always use full HTTP responses for redirects and Set-Cookie.
SSG
Static generation runs at build time. HTML is served as a static asset (still hydrates when needed).
getStaticPaths
For parameterized SSG routes, return full pathnames:
{
path: '/docs/:slug',
component: Doc,
render: 'ssg',
getStaticPaths: () => ['/docs/intro', '/docs/api'],
}Prefer getStaticPaths; entries is an alias. Routes with :params and no path list are skipped at build.
ISR: revalidate
By default SSG HTML is immutable until the next avedon build. Set revalidate (seconds) for stale-while-revalidate in production (avedon start):
revalidate |
Behavior |
|---|---|
| omitted | Forever static |
N > 0 |
After N seconds, next GET returns cached HTML and regenerates in the background |
0 |
Every request treated as stale (regen deduped per path) |
Not in v1: on-demand revalidatePath / tags, or regenerating paths that were never built. avedon dev does not run the disk ISR loop.
CSR
Client-side rendering skips server HTML for the page body beyond the application shell. Guards still apply when configured. Use for app-like surfaces or auth-gated views that are not meant for public HTML snapshots.
Mixing modes
One routes.ts can mix ssg, ssr, and csr. Choose per route.
Build output
avedon build produces client assets, server bundles, and SSG HTML. The Node adapter serves production via avedon start — see Deployment.