This is for those who would like to think they know precisely what they mean.

Skip to:


It is recommended you start by building a Snowman. The Snowman is a minimal "Hello World" example repo where you can build a Shpadoinkle application. This project should work with any system capable of compiling code with GHC. This project is built with Nix but stack is also supported.


If you do not have Nix, please follow the instructions located here. You may also follow the TLDR version below:

curl -L https://nixos.org/nix/install | sh
# Follow the instructions printed by the above command
nix --version
nix-env -iA cachix -f https://cachix.org/api/v1/install
cachix use shpadoinkle
git clone https://gitlab.com/fresheyeball/Shpadoinkle-snowman.git
cd Shpadoinkle-snowman

Now you should be set up with a development environment. Standard cabal toolchain should work out of the box as well as ghcid.


If you do not wish to use Nix, you may also build a Snowman with stack. This should work out of the box, using standard stack commands.

curl -sSL https://get.haskellstack.org/ | sh
stack --version
git clone https://gitlab.com/fresheyeball/Shpadoinkle-snowman.git
cd Shpadoinkle-snowman
stack build

however you will not benefit from cachix caching and this will take some time for the initial compile.


Shpadoinkle Html is an opt in module for generating Shpadoinkle Core’s Html types.

Each Html tag has named functions, including a plain version that accepts properties [(Text, Prop a)] and children [Html a]. Adding an underscore allows you to pass no properties. Adding a prime allows you to pass no children.

h1 [ id' "foo" ] [ text "bar" ]

will render as

<h1 id="foo" >bar</h1>

Text nodes, being extremely common, have an extra overloaded API.

h1 [ id' "foo" ] [ "bar" ]

will work as well. Provided you have enabled OverloadedStrings.

CSS Classes

Due to the frequency of use, CSS classes have a polymorphic overloaded API. This includes multiple representations, all of which become ClassList, which is just a newtype of Set Text.

To learn more about the HTML package see docs here.


Event handling is achieved through properties. There are several named functions for each event type and a few additional helpers. A plain version for pure handlers, an M version for monadic handlers, and a C version for working with `Continuation`s.

const div = document.createElement("div")
div.addEventListener("click", doit)

is morally equivalent to

div' [ onClick doit ]

Next we will use these concepts to build a calculator, in part 2.