Static Prerendering
for Phoenix
Generate static HTML at build time. Serve instantly from disk. Keep pages fresh with incremental regeneration. All on the BEAM.
Four Rendering Modes
This demo showcases every rendering strategy. Each page shows its mode in the top-right badge.
Static at Build Time
HTML generated once via
mix phoenix.prerender
and served directly from disk. Zero runtime cost.
Static First, Then Live
Prerendered as static HTML for instant load, then hydrated via WebSocket for interactivity.
Stale-While-Revalidate
Serve stale content instantly while regenerating in the background. Pages stay fresh without rebuilds.
Server-Rendered
Standard Phoenix pages. Every request hits the router, controller, and template engine. No prerendering.
How It Works
Mark Routes
Use the prerender macro
in your router to tag routes for static generation.
prerender do
get "/about", PageController, :about
live "/changelog", ChangelogLive
end
Generate
Run the Mix task to render each route through your full endpoint pipeline and write HTML to disk.
$ mix phoenix.prerender
Generated 6 pages
Wrote manifest.json
Wrote sitemap.xml
Serve
The plug serves static files before they hit the router. ISR keeps them fresh in the background.
# endpoint.ex
plug PhoenixPrerender.Plug
plug MyAppWeb.Router
Instant Response
Static HTML served via send_file. No database, no templates, no rendering at request time.
ISR
Stale-while-revalidate keeps pages fresh. ETS locks prevent thundering herd.
Distributed
Cluster-wide locking via :global.trans. PubSub cache invalidation across nodes.
Atomic Writes
Write to .tmp, rename to final. Readers never see partially written files.
Telemetry
Events for generate, render, serve, and regenerate. Plug into your metrics stack.
Mix Task + CI
mix phoenix.prerender with --path, --style, --concurrency flags. Drop into any CI pipeline.