The beauty of LiveView

Lately we have been working on Bytepack to help developers deliver and sell packages to companies and enterprises.

In Bytepack, authors can push new packages at any time. Publishing said packages is done with your usual package manager tool, such as mix hex.publish in Elixir or npm publish for Node.js. Once you call these commands, the request goes to specific endpoints that implement the Hex.pm and npm APIs.

The specific steps are shown in our “New package” page:

ytepack new package screen

The /packages/new route is a Phoenix LiveView that looks like this:

defmodule BytepackWeb.PackageLive.New do
  use BytepackWeb, :live_view

  def mount(params, session, socket) do
    socket = authenticate(socket, session)
    {:noreply, socket}
  end

  def render(assigns) do
    ~L"""
    ...HTML template...
    """
  end
end

Nothing special so far. But here is where LiveView is a big deal.

To improve the user experience, we also wanted to automatically update the browser with the package information whenever the user publishes it. Implementing this functionality in LiveView requires three changes.

First we broadcast an event whenever a package is created to a “package:new” topic under the user:

Phoenix.PubSub.broadcast(
  Bytepack.PubSub,
  "user:#{user.id}:package:new",
  {:published, package.id}
)

Back in PackageLive.New, we change mount/3 to also subscribe to said topic:

def mount(params, session, socket) do
  socket = authenticate(socket, session)

  if connected?(socket) do
    Phoenix.PubSub.subscribe(
      Bytepack.PubSub,
      "user:#{socket.assigns.current_user.id}:package:new"
    )
  end

  {:noreply, authenticate(socket, session)}
end

and then write a clause to handle said events:

def handle_info({:published, package_id}, socket) do
  {:noreply, live_redirect(socket, to: "/packages/#{package_id}")}
end

And that’s it! Now we redirect the browser to the newly created package page whenever the package is published.

ytepack new package screen

We didn’t have to:

  • manually establish WebSockets or long-polling connections
  • create a separate endpoint to send requests to
  • define a specific JSON payload between client/server
  • write any front-end glue code
  • setup third-party dependencies for pubsub, such as Redis, nor anything else to run at scale
  • etc

Compared to what others have built with LiveView, this is absolutely trivial. However, the fact we can set this up in less than 2 minutes is that excites me!

LiveView comes with its own integrated testing story too. We can test everything from the comfort of Elixir, without a need to bring heavy-hitters such as Selenium or any webdriver.

To run in development, we only need to start our Phoenix server. We don’t need external tooling in production either. We can deploy this to Fly.io or Gigalixir, configure clustering, and everything just works across multiple nodes.

While this is a very limited sample of what LiveView can do, it highlights the beauty of its model and, perhaps more importantly, it shows all of the things we don’t have to manage nor worry about. At the end of the day, the Bytepack team can focus more on the user experience than we would otherwise, thanks to LiveView’s accessibility.