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.

Prerendered

Static at Build Time

HTML generated once via mix phoenix.prerender and served directly from disk. Zero runtime cost.

LiveView + Prerender

Static First, Then Live

Prerendered as static HTML for instant load, then hydrated via WebSocket for interactivity.

ISR

Stale-While-Revalidate

Serve stale content instantly while regenerating in the background. Pages stay fresh without rebuilds.

Dynamic

Server-Rendered

Standard Phoenix pages. Every request hits the router, controller, and template engine. No prerendering.

How It Works

1

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
2

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
3

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.