Launching Projects with Elm and Elixir

Sometimes the most painful part of learning a new language isn’t picking up the new syntax or libraries or logic — it’s figuring out all the supporting technologies. How do you compile Javascript? How do you hook OAuth into your session management? How do you even manage sessions?

This year I’ve fallen in love with Elm and Elixir, in large part because of the way those two languages push me to think differently about development. When I started on my second Elm and third Elixir project, I was excited to get straight to hacking, but challenges quickly emerged.

Elixir and the Phoenix framework are straightforward to set up, and adding Elm compilation isn’t too difficult either. However, as I added authentication through Twitter and moved auth to the API and put everything into Docker and and and, I found myself spending more and more of my time setting up the projects right rather than learning Elm and Elixir better or actually building the app I wanted to create.

Wouldn’t it be nice to jump straight to coding instead, and pick up the infrastructure along the way?

For anyone who’s felt the same way, or who’s thinking about trying out Elm and Elixir, look no further: there’s now a way to leap those hurdles.

Introducing the Elm+Elixir Starter Kit

I’m excited to release the Elm+Elixir Starter Kit, a new boilerplate project combining Elm and Elixir, ready with an easy, scripted setup for developers who are excited to experiment and build on these technologies. If you want to hit the ground running, check it out on Github!

Features

When you clone the repo, you’ll get

  • Elixir 1.4.4 for the backend, with Phoenix 1.2.1 configured for Postgres
  • Elm 0.18 for the frontend
  • Authentication through Twitter (extensible to other providers through Guardian/Ueberauth)
  • Independent frontend that communicates to the backend using JSON API calls
  • Elixir tests and code linting/static analysis via ExUnit and Credo
  • Elm compilation tests and code listing via elm-make
  • Ready for continuous integration on Circle CI
  • Yarn for deterministic Javascript package management
  • Configured for Docker for easy development and deployment

How does it work?

Curious about how the Starter Kit is implemented? Here’s an overview of some of the more interesting or challenging parts of the app.

How do we compile Elm to Javascript?

The Phoenix framework uses the Brunch asset pipeline for static assets, so it’s actually quite straightforward to get Elm compiling. As described in @diamondgfx’s useful blog post, you just need to add the brunch-elm packages to package.json and set up the Elm section of your brunch-config.js appropriately. (This is also how the app handles SASS.)

How do we set up Twitter login?

Modern-day OAuth involves three parties: your browser, the app’s server, and an OAuth provider like Twitter. You log into Twitter with your browser; Twitter then redirects you back to the app with a special code in the URL. The app server talks behind the scenes with Twitter to validate that code and get your account info. In the halcyon days of yore we had to set this up ourselves, but fortunately there are great libraries these days to make it easy.

In Elixir, the combination of Ueberauth and Guardian take care of OAuth (similarly to how Omniauth and Devise in Ruby). Once you’ve configured Ueberauth in your app’s config.exs, hitting /auth/twitter will redirect you to the login URL with all the parameters Twitter needs to identify the app. When the user returns, Ueberauth validates the response and gets the authenticated user info, which the the starter kit handles in the AuthController.

Once the app has a validated Twitter account, Guardian takes care of everything to do with your local user record. It provides a number of useful plugs to ensure that users are loaded or authenticated, making use of the GuardianSerializer module to encode user information into and out of the session.

How do you get user info on the frontend?

Here’s where things get really interesting. How does Elm know whether a user is logged in?

Elixir has a templating language (EEx). Since the backend Phoenix app is the source of truth, we could simply pass that information into Elm on initialization:

var app = Elm.MyApp.fullscreen({
// Poison is an Elixir JSON library
user: <%= Poison.encode!(user) %>
});

Hard-coding the user data in the template would be straightforward and fast, but if that approach unsettles you a little you’re not alone. Either your app only knows how to get user data on load, requiring a refresh whenever it changes, or you have to have multiple mechanisms to get the user data, which adds all the risks of code duplication.

Instead the Elm+Elixir Starter Kit loads the user data via a JSON API. When you create an Elm app, you can specify the starting command, which the Starter Kit uses to immediately identify the user:

main : Program Never Model Msg
main =
Html.program { init = ( Model.init, UserApi.validateUser ), view = view, update = update, subscriptions = subscriptions }

(Never seen Elm before? Here’s a tutorial that explains what this code does.)

The UserApi Elm module makes a request to Phoenix, which knows the user state. That response is incorporated into the model for the views to consume.

What about Docker?

The Starter Kit is set up with Docker so you can build an image once and use it for development, testing, and production. The Docker image contains Elixir, Elm, and all the packages we need to run and test the code. For local development, the app uses docker-compose to set up Postgres as well; to avoid checking any passwords or secrets into source control, it reads from a git-ignored development.env file (a template for that is provided).

Try it out!

Ready to start your own project? Just want to kick the tires a bit? Awesome!

1. Clone or fork the repo:

git clone git@github.com:arsduo/elm-elixir-starter.git

2. Use the included ./setup_project.sh script to configure the starter kit for your project:

3. Try it out!

If everything’s working, Docker will boot up:

And you’ll see this handsome welcome screen:

You can log in through Twitter:

And then you’ll be back at the app with access to your Twitter user:

What’s next?

As a relative newbie to Elm, Elixir, and Docker, I’m sure there are plenty of good practices you know of that I’ve missed — thoughts, suggestions, and Github issues and especially pull requests are very welcome!

I’ve been using the Starter Kit for a personal project focusing on books, and it’s been hugely helpful! With a few more apps in mind, I know this will come in handy for me — and hopefully for you as well.

I’d love to hear about your experience using the Elm+Elixir Starter Kit, what you’re doing with it, and certainly anything that got in your way.

Enjoy!