/library / template-phoenix-liveview
templateWeb app

Phoenix LiveView app (Elixir realtime, no JS framework)

A full-stack Elixir app with Phoenix LiveView. Server-rendered, realtime updates over WebSocket, no React. Use when you want realtime collaboration features without the JS-state-management circus.

use whenRealtime dashboards, multiplayer apps, internal tools, anything where 'live updates from the server' is the core UX and you'd rather not maintain a separate frontend.

May 13, 20262,240 byteselixirphoenixliveviewrealtimebeam

[App Name] · Phoenix LiveView

A LiveView app. Server-rendered HTML over WebSocket. Realtime updates without a JS framework.

Source of truth

Production runs as a Phoenix release on Fly.io (BEAM clusters across Fly regions). Postgres in the same primary region with read replicas elsewhere. The Phoenix release tarball is canonical.

Tech stack

Elixir 1.18 + Phoenix 1.8 + LiveView 1.0 + Phoenix.PubSub for cross-process messaging. Ecto + Postgres. Tailwind v4 (built via esbuild + tailwind ports). Oban for background jobs. ExUnit for tests. Deployed via Fly's Elixir launcher.

Deploy

fly deploy from local. Releases are built via mix release inside the Fly builder. Postgres on Fly.

File map

  • lib/myapp/ business domain (Ecto schemas, contexts)
  • lib/myapp_web/ web layer (LiveView modules, controllers, components)
  • lib/myapp_web/live/ LiveView modules, one per major surface
  • lib/myapp_web/components/ reusable function components
  • lib/myapp/repo.ex Ecto repo
  • lib/myapp/application.ex supervision tree (PubSub, Repo, Endpoint, Oban)
  • priv/repo/migrations/ Ecto migrations
  • assets/ Tailwind + esbuild entrypoints
  • mix.exs deps + release config
  • fly.toml

.env keys

  • DATABASE_URL
  • SECRET_KEY_BASE (generate with mix phx.gen.secret)
  • PHX_HOST your prod hostname
  • POOL_SIZE Ecto pool, default 10

Hard rules

  • Business logic in contexts, NOT in LiveView modules. LiveView is the UI layer.
  • assign everything you read in the template into socket.assigns. NEVER read from sockets implicitly.
  • For lists with thousands of items, use streams (stream/4). Don't put 10k items into assigns.
  • Phoenix.PubSub for any cross-LiveView communication. Don't hand-roll Channels.
  • Migrations are reversible (up AND down). Tested with mix ecto.rollback.
  • Use Oban for anything async. Don't Task.start in handlers; restarts will leak.

Recent significant changes

  • 2026-05-13: Scaffolded. Locked: LiveView 1.0 (stable now), Oban over Quantum (better persistence), Fly over Render (BEAM clustering across regions matters).

Next session: start here

  1. mix phx.new myapp --live to scaffold (or apply this CLAUDE.md over an existing scaffold).
  2. Create the first context with mix phx.gen.live. Run it, click around.
  3. Set up Tailwind v4 via the tailwind mix task.
  4. Add Oban. Define one worker. Confirm it processes.
  5. fly launch + fly deploy. Confirm /live heartbeat survives a deploy.

Get the next CLAUDE.md in your inbox.

One new template every week, plus occasional case studies.