/hnlive

A Phoenix/LiveView web app showing the top 10 (by score or number of comments) newest HackerNews stories in "real time".

Primary LanguageElixirMIT LicenseMIT

HNLive

HNLive is a small Elixir/Phoenix/LiveView web app showing the top 10 (by score or number of comments) newest HackerNews stories in "real time" (i.e. as quickly as updates become available via the HackerNews API).

You should find the app running on https://hntop10.gigalixirapp.com - please note that this is running on the free tier with limited memory and resources.

A screenshot of the HNLive app, showing the top 10 newest HN posts sorted by score

As seen in the screenshot above, updated rows (i.e. position, score or number of comments has changed) are briefly highlighted using a light orange background. The theme currently used by the app was kindly provided by josefrichter.

The motivation for building HNLive was twofold:

  • I had read and heard many good things about Elixir, Phoenix and LiveView, and after watching Chris McCord`s demo "Build a real-time Twitter clone in 15 minutes with LiveView and Phoenix 1.5", I finally said to myself: "That looks awesome, time to learn Elixir and Phoenix!" HNLive is the app I built over the last couple of days while on this learning journey, so don't expect idiomatic or bug-free code - feel free to point out potential improvements!
  • I love browsing HackerNews, but for me the selection of stories on the front page, the "newest" page and the "best" page is not ideal if I want to see at a glance which new stories (say, submitted over the course of the last 12 hours) have received the most upvotes or are discussed particularly controversially (as judged by the number of comments). HNLive attempts to address this using data from the HackerNews API to provide the top 10 submissions, sorted by score or number of comments, taking into account only the last 500 submissions. I also wanted to see updates to the top 10 (and scores and number of comments) in real time, which was made easy by using LiveView.

To start hacking on HNLive:

  • Make sure that Erlang, Elixir and Node.JS are installed, see the Phoenix installation instructions for a guide. HNLive does not require PostgreSQL.
  • Clone the git repository with git clone https://github.com/gstipi/hnlive.git
  • Setup the project with mix setup
  • Start Phoenix endpoint with mix phx.server

Now you can visit localhost:4000 from your browser.

How would you run this in production? Please check the official Phoenix deployment guides.

In order to get this up and running on Gigalixir, I used the official Gigalixir documentation.

Some remarks on the project structure and Elixir/Phoenix/LiveView features used

HNLive.Api

HNLive.Api contains the required functionality for querying the HackerNews API, in particular the v0/newstories and v0/updates endpoints. To retrieve many stories concurrently, Task.async/Task.await are used.

I rely on the :max_connections setting of the hackney pool used by HTTPoison to limit the number of concurrent queries in flight to 30 (:max_connections is set when starting the hackney pool as part of the supervision tree in HNLive.Application).

HNLive.Watcher

HNLive.Watcher is a GenServer, providing updates via Phoenix.PubSub when the top stories change.

When the watcher starts, the 500 newest stories are initially retrieved using HNLive.Api.get_newest_stories/0. Afterwards, every 10 seconds updates are downloaded using HNLive.Api.get_updates/0 and HNLive.Api.get_many_stories/1. The updated stories are then merged with the previously retrieved stories.

Only the 500 newest stories are considered (and kept in memory) when updating the top 10 stories by score and number of comments.

The watcher also broadcasts updates when the number of subscribers to the corresponding PubSub topic changes, which is used to display the number of current visitors in the associated LiveView. The number of subscribers is tracked by SubscriberCountTracker, which implements the Phoenix.Tracker behaviour.

HNLiveWeb.PageLive

HNLiveWeb.PageLive is the actual LiveView, which renders the top stories and current visitor count whenever they are updated. To receive these updates, the LiveView subscribes to the HNLive.Watcher (or better, the PubSub topic the watcher broadcasts to).

It also allows switching between sorting the stories by score and sorting by number of comments - this is implemented using Phoenix.LiveView.handle_params/3.

The CSS used in the LiveView is a naive attempt to re-create the spirit of the original HackerNews layout, using a responsive Flexbox layout.

Additional notes

Initial project created with the Phoenix generator: mix phx.new hnlive --module HNLive --live --no-ecto

I also had to update to latest Phoenix and LiveView versions in mix.exs:

{:phoenix, "~> 1.5.3"},
{:phoenix_live_view, "~> 0.13.0"},

The only additional dependency I included was HTTPoison, which I also added in mix.exs:

{:httpoison, "~> 1.6"}

To the supervision tree in HNLive.Application, add

# Hackney pool used for HTTPoison requests
:hackney_pool.child_spec(:httpoison_pool, timeout: 15000, max_connections: 30)

Run mix deps.get to retrieve updated dependencies.

Add /.elixir_ls/ to .gitignore if using ElixirLS.

MIT licensed.