DEV Community

Alex Spinov
Alex Spinov

Posted on

Phoenix LiveView Has a Free API — Real-Time Apps Without JavaScript

Phoenix LiveView is Elixir's real-time web framework that lets you build interactive apps without writing JavaScript. The entire stack is free and open source.

Why Phoenix in 2026?

Phoenix handles 2 million concurrent WebSocket connections on a single server. While Node.js struggles at 10K connections and Rails needs Redis for pub/sub, Phoenix does it natively with Erlang's BEAM VM.

What You Get for Free

  • LiveView — real-time UI without JavaScript
  • PubSub — built-in real-time messaging (no Redis needed)
  • Presence — track who's online (built-in, no external service)
  • Channels — WebSocket support out of the box
  • Ecto — powerful database query DSL
  • Mix — build tool, test runner, formatter, all built in

LiveView: Interactive UI Without JS

defmodule MyAppWeb.CounterLive do
  use MyAppWeb, :live_view

  def mount(_params, _session, socket) do
    {:ok, assign(socket, count: 0)}
  end

  def render(assigns) do
    ~H"""
    <div class="text-center p-8">
      <h1 class="text-4xl font-bold"><%= @count %></h1>
      <div class="space-x-4 mt-4">
        <button phx-click="decrement" class="btn">-</button>
        <button phx-click="increment" class="btn">+</button>
      </div>
    </div>
    """
  end

  def handle_event("increment", _, socket) do
    {:noreply, update(socket, :count, &(&1 + 1))}
  end

  def handle_event("decrement", _, socket) do
    {:noreply, update(socket, :count, &(&1 - 1))}
  end
end
Enter fullscreen mode Exit fullscreen mode

This is a fully interactive counter — click events, state updates, DOM patches — all over WebSocket. Zero JavaScript written.

Real-Time Chat in 30 Lines

defmodule MyAppWeb.ChatLive do
  use MyAppWeb, :live_view

  def mount(_params, _session, socket) do
    if connected?(socket) do
      Phoenix.PubSub.subscribe(MyApp.PubSub, "chat:lobby")
    end
    {:ok, assign(socket, messages: [], message: "")}
  end

  def handle_event("send", %{"message" => msg}, socket) do
    Phoenix.PubSub.broadcast(MyApp.PubSub, "chat:lobby", {:new_message, msg})
    {:noreply, assign(socket, message: "")}
  end

  def handle_info({:new_message, msg}, socket) do
    {:noreply, update(socket, :messages, &[msg | &1])}
  end

  def render(assigns) do
    ~H"""
    <div class="chat-container">
      <div :for={msg <- Enum.reverse(@messages)} class="p-2 border-b">
        <%= msg %>
      </div>
      <form phx-submit="send" class="mt-4">
        <input name="message" value={@message} placeholder="Type..." class="input" />
        <button type="submit" class="btn">Send</button>
      </form>
    </div>
    """
  end
end
Enter fullscreen mode Exit fullscreen mode

Real-time chat. Multiple users. No Redis. No Socket.io. No JavaScript.

Presence Tracking (Who's Online)

defmodule MyAppWeb.Presence do
  use Phoenix.Presence,
    otp_app: :my_app,
    pubsub_server: MyApp.PubSub
end

# In your LiveView:
def mount(_params, _session, socket) do
  if connected?(socket) do
    MyAppWeb.Presence.track(self(), "room:lobby", socket.assigns.current_user.id, %{
      name: socket.assigns.current_user.name,
      joined_at: DateTime.utc_now()
    })
  end

  presences = MyAppWeb.Presence.list("room:lobby")
  {:ok, assign(socket, users_online: map_size(presences))}
end
Enter fullscreen mode Exit fullscreen mode

Quick Start

# Install Elixir
brew install elixir  # macOS
# or: curl -fsSL https://elixir-lang.org/install.sh | bash

# Create Phoenix project
mix archive.install hex phx_new
mix phx.new my_app --live

# Setup and run
cd my_app
mix setup
mix phx.server
Enter fullscreen mode Exit fullscreen mode

Phoenix vs Next.js vs Rails

Feature Phoenix Next.js Rails
Real-time Built-in (LiveView) Needs Socket.io Needs ActionCable + Redis
Concurrency 2M connections/server ~10K connections ~1K connections
Presence Built-in External service External service
PubSub Built-in Redis/external Redis
Fault tolerance Erlang supervisors Process crashes Process crashes
Hot reload Built-in Built-in Built-in

Need to scrape data from any website and get it in structured JSON? Check out my web scraping tools on Apify — no coding required, results in minutes.

Have a custom data extraction project? Email me at spinov001@gmail.com — I build tailored scraping solutions for businesses.

Top comments (0)