DEV Community

Cover image for "elm-starter", a tool for the Modern Web

Posted on • Originally published at Medium

"elm-starter", a tool for the Modern Web

Lately there has been some interesting discussion about Modern Web.

I personally think that

  • Single Page Applications (SPAs) have been (ab)used in places where a more traditional server side approach could have been a better fit
  • SPAs require extra care (navigation, scrolling, accessibility, SEO, etc.)
  • There are many SPAs that are not well crafted but when they are well made, SPAs can very much enhance the user experience
  • The browser feels like the natural place where to handle complex UIs, not the Server
  • As developers, I (we?) like to keep using my best tools to improve the Developer Experience

Related to the last point I feel that the Elm language come with a curse:

"Once you are in Elm, you want to stay in Elm"

This is not happening only with Elm, but with any compiled-strictyly-typed-inferred-immutable-purely-functional-with-nice-errors language.

So to alleviate some of these issues I made a small script to convert Elm SPAs into Statically Generated Progressive Web Applications (PWAs), called elm-starter.

(Yes, another one)


The goal is to have a tool that

  • Is mainly written in Elm (see the curse mentioned above)
  • Supports the majority of Elm libraries (elm-ui, elm-spa, etc.)
  • Relatively simple to use
  • Can be used to bootstrap a new app or to convert an existing one
  • Is not invasive and can be removed at any time

The resulting PWA should have these characteristics

  • Works without Javascript
  • Works off-line
  • Is installable on mobile/desktop
  • Is friendly to bots (SEO)
  • Supports preview cards
  • Renders fast (gets high scores in Lighthouse)

The classic Lighthouse screenshot with confetti 🎉

The classic Lighthouse screenshot with confetti

High scores with Lighthouse. Well, it is an almost empty app, but still...

Preview cards in Slack:

Preview cards in Slack

Preview cards in Slack. Different routes have different previews

What does this tool do?

  • Generates all the needed files for a PWA
  • Centralize in one "single-source-of-truth" all metadata
  • Generates static pages

This is all. Quite simple!


There are 3 demos made with elm-starter:

Alt Text

The 3 demos made using `elm-starter`, seen here in their installed version on macOS.

1. The official elm-starter demo

This is a simple SPA with an SVG object. It is an example of one of the differences between SPA and MPA: page transition. This app works both with and without Javascript. The only difference is that: No Javascript -> No page transition.

Note that the page transition is made with CSS transition applied to SVG. I realized too late that this is only supported in Chrome and I didn't have the time to change it, but you get the picture.

Here is the difference between having Javascript ON or OFF:

Alt Text

The first series of clicks is with Javascript enabled, the other clicks are with Javascript disabled.

2. Todo MVC

This is the classic Todo MVC, the one that I used extensively to compare different frameworks in a past article.

It was originally coded by Evan Czaplicki, I just adjusted it to fix some accessibility issues.

Compared to the previous demo, this one doesn't work without Javascript for its nature.

The preview card on Slack:

The preview on Slack

3. elm-spa Example

This example shows a possible synergy between elm-spa, a nice way to create complex SPAs that take care of several things for you through automatic Elm code generation. For example, to create new pages you simply run a command in the terminal and this creates the right files, routes and logic for you.

elm-starter can then take over and transform it in a PWA, statically generating all routes.

In this specific example all pages are accessible without Javascript, but the widget that requires Javascript (like the counters) will not be working.

The preview card on Slack:

The preview card on Slack

Behind the scenes

  • All files are generated by Elm code:

    • HTML: Generated using a modified version of zwilias/elm-html-string. For example Index.elm generates index.html.
    • JSON: Generated using elm/json. For example Manifest.elm generates manifest.json.
    • CSS: Generated from strings. I know, this is not ideal. rtfeldman/elm-css, that is CSS with the type-safety of Elm, seems not exposing the toString converter. The quantity of CSS necessary in elm-starter is very small anyway so I kept it as a string. For example SnippetCss.elm.
    • Javascript: Generated from strings. Again, the quantity of Javascript needed to run the App is minimal so I made the trade-off of saving it as string. For a larger amount of Javascript it is better to keep it in .js files. For example SnippetJavascript.elm.
  • All static pages and snapshots are generated using Puppeteer.

  • Most of the CSS and Javascript is formatted "comma-leading" or "semicolon-leading" (sorry, I could not resist, see the Elm curse above, again)

This is a snapshot of Index.elm that generates index.html:

Alt Text


Each page is statically generated with specific meta-tags so that search engine spiders can easily pick it up, also when they are not as sophisticated as Google, that is able to execute Javascript since a long time ago.

Someone says that even if Google can run Javascript, it still prefers static websites.

This is how Google indexed the elm-starter demo after few days from its launch:

Google indexing the elm-starter demo

Google indexing the elm-starter demo

Similar projects

These are other excellent projects that can be used to bootstrap an Elm application or to generate a static site:

About Modern Web vs. Traditional Web

To get more insights about the debate mentioned at the beginning of this post:

How to use elm-starter

You can find elm-starter at

The fastest way to start using it is by clicking this button:

Deploy to Netlify

This will automatically

  • Create a repository containing elm-starter into your Github account
  • Deploy it live using your Netlify account

To modify the app simply clone the new repo on your computer and run:

$ npm install
$ npm start
Enter fullscreen mode Exit fullscreen mode

Now you can edit src/Main.elm and, after confirming the result at http://localhost:8000, commit your modifications to Github.

The new app will be published live automatically by Netlify in seconds, including re-generating all static pages.

More information available in the README.

This is all, thank you for reading! ❤️

Cover image: Mount Fuji seen from Kawaguchi lake by WorldInMyEyes from Pixabay

Top comments (3)

gayanhewa profile image
Gayan Hewa

Good stuff mate. Going to be helpful for a lot of those who are dipping their toes on Elm.

sergix profile image
Peyton McGinnis • Edited

I've also come across Mint which is competing with Elm for the "dedicated SPA language" spot. Personally, I prefer Mint's syntax.

wolfadex profile image
Wolfgang Schuster

Mint definitely fits more if you're uncomfortable switching away from the C style of syntax. Having been building web sites for 2 decades now, for me, Elm has been amazing to have. But, it's not for everyone and that's cool too.