Say Yo ! Or how to kickstart your Elm Spa in a snap

Lately I was animating an Elm Workshop at work. One of my teammates who was attending the session asked me the following question :

How do you create a multipage application with Elm ?

When I introduce Elm to beginners, I always recommend for them to go and read the official Elm Guide. It’s an awesome resource with very simple examples to get them started.

So i sent her the navigation chapter of the guide that shows how to build an SPA (Single Page Application) with Elm. I asked her to read it and follow the tutorial to build her program.

The code provided in the guide is very straightforward:

import Browser
import Browser.Navigation as Nav
import Html exposing (..)
import Html.Attributes exposing (..)
import Url



-- MAIN


main : Program () Model Msg
main =
Browser.application
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
, onUrlChange = UrlChanged
, onUrlRequest = LinkClicked
}



-- MODEL


type alias Model =
{ key : Nav.Key
, url : Url.Url
}


init : () -> Url.Url -> Nav.Key -> ( Model, Cmd Msg )
init flags url key =
( Model key url, Cmd.none )



-- UPDATE


type Msg
= LinkClicked Browser.UrlRequest
| UrlChanged Url.Url


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
LinkClicked urlRequest ->
case urlRequest of
Browser.Internal url ->
( model, Nav.pushUrl model.key (Url.toString url) )

Browser.External href ->
( model, Nav.load href )

UrlChanged url ->
( { model | url = url }
, Cmd.none
)



-- SUBSCRIPTIONS


subscriptions : Model -> Sub Msg
subscriptions _ =
Sub.none



-- VIEW


view : Model -> Browser.Document Msg
view model =
{ title = "URL Interceptor"
, body =
[ text "The current URL is: "
, b [] [ text (Url.toString model.url) ]
, ul []
[ viewLink "/home"
, viewLink "/profile"
, viewLink "/reviews/the-century-of-the-self"
, viewLink "/reviews/public-opinion"
, viewLink "/reviews/shah-of-shahs"
]
]
}


viewLink : String -> Html msg
viewLink path =
li [] [ a [ href path ] [ text path ] ]

We won’t go into the details of this snippet (The Elm guide gives great explanations), but as you can see, it’s kind of a lot of boilerplate to write !

From here I realized that every time someone needs to create a small App in Elm, he will have to:

  1. Visit the Guide;
  2. Find this snippet;
  3. Copy and paste this code into his editor;
  4. Install dependencies;
  5. Run the App.

Come one! There should be a better way to do that!

Just use a boilerplate

Many people have already come across this question.

How can I get started quickly when building a new Elm App ?

The obvious answer is to use a “Boilerplate”.
In Elm here are the most famous ones:

Although these are awesome projects that can help you get productive very quickly, they suffer from the same drawbacks: They come with a bunch of tools that you may not need at the beginning and especially when you are just learning Elm.

Webpack, Service Worker, Live reloading, Server Side Rendering etc…. These are great tools that come out of the box with such boilerplates, but they add some complexity

Just say Yo !

Then I remembered this project I heard about those days, when I was doing some angular JS: Yeoman

Yeoman helps you to kickstart new projects, prescribing best practices and tools to help you stay productive.
To do so, we provide a generator ecosystem. A generator is basically a plugin that can be run with the ‘yo’ command to scaffold complete projects or useful parts.
(Official Yeoman Documentation)

This is exactly what we need. Just say ‘yo’ and it generates an Elm app for you.

Here comes Elm Starter Kit Generator

So i created a simple Yeoman Generator called Elm-starter-kit.
The goal of this command is to help you create and bootstrap a minimalist Elm Application. No webpack, no modules, just a single Main.elm file with a minimal amount of code to run your application.

Just to be clear, it’s not meant to replace boilerplates, but it can be used at first before moving to them once your project becomes more complex.

Let me show you how it works:

Just open a new folder and run the following commands

  1. npm i -g yo && npm i -g generator-elm-starter-kit;
  2. yo elm-starter-kit;
  3. Enter the name of your project;
  4. Select the type of the application (sandbox, application etc….)
  5. After the installation is complete, your app is running on htttp://localhost:8000.

Starting your project like this comes with the following advantages:

  • No need to copy and paste some code manually. It’s fast and direct.
  • The code fits in a single Main.elm file. It’s a known best practice to start your application small and add modules only when you app starts to be big and hard to reason about (see the Life of a File by Evan Czaplicki)

Conclusion

I find that sometimes it’s very difficult for people learning a new language to find good examples to get started. Elm maintainers did a great job with the documentation, Elm Guide etc…. But still, people want to get productive very quickly.

Boilerplates are great for that, but they can come with a high cost in complexity.

In this article we have seen that Elm Starter kit is just another tool that can be added to your toolbox if you want to start your Elm journey in a fast and simple way.

And you? What tool do you use when you have a new Elm app to create?