Working sample of a SAFE-Stack project that uses CQRS/Event-Sourcing and the Elm Architecture
Clone or download
rommsen Merge pull request #59 from nilshelmig/patch-1
Fix broken link to Fable-Elmish
Latest commit 26ebf27 May 15, 2018
Failed to load latest commit information.
.paket Use latest paket.bootstrapper.exe in magic mode Feb 24, 2018
public Favicons / About page Dec 31, 2017
sass [UI] Notifications Toasty style Dec 14, 2017
src Remove dummy Apr 11, 2018
.editorconfig new page 'conference' Sep 5, 2017
.gitignore Build group for fake. Different Bootstrap files. mode for webpack Apr 10, 2018
.travis.yml Bump node version Apr 11, 2018
ConfPlanner.sln New Project: Conference.API Nov 14, 2017
LICENSE Add License - fixes #50 Dec 31, 2017
NuGet.config Added Fable Elmish Template and changed alot of stuff to make it work Aug 29, 2017 Fix broken link to Fable-Elmish May 15, 2018 Everything is dotnet core2, build script restores everything and rest… Sep 2, 2017
build.cmd Build group for fake. Different Bootstrap files. mode for webpack Apr 10, 2018
build.fsx Do not call yarn-start anymore Apr 11, 2018 Build group for fake. Different Bootstrap files. mode for webpack Apr 10, 2018
global.json Use global.json for dotnet sdk version Apr 10, 2018
package-lock.json Added Fable Elmish Template and changed alot of stuff to make it work Aug 29, 2017
package.json Build group for fake. Different Bootstrap files. mode for webpack Apr 10, 2018
paket.dependencies Build group for fake. Different Bootstrap files. mode for webpack Apr 10, 2018
paket.lock Build group for fake. Different Bootstrap files. mode for webpack Apr 10, 2018
webpack.config.js Webpack 4.5, updated webpack.config Apr 10, 2018
yarn.lock Webpack 4.5, updated webpack.config Apr 10, 2018

SAFE - A web stack designed for developer happiness

The following document describes a SAFE-Stack sample project that brings together CQRS/Event-Sourcing on the backend and the Elm architecture on the frontend.

SAFE is a technology stack that brings together several technologies into a single, coherent stack for typesafe, flexible end-to-end web-enabled applications that are written entirely in F#.



Build Status

This is the sample project that is used in the talk "Domain Driven UI" (Slides). The title is a bit misleading as it is a bad name for "Reusing your datatypes and behaviour from your CQRS/Event-Sourced models in your Elm-architecture application."

Given you use F# and Fable, you can actually build simple eventually connected systems and have the exact same model working in back and frontend.

The application showcases a couple of things:

  • The reuse of the complete domain model on the client and server.
  • It shows the nice fit of and similarity between CQRS/Event-Sourcing on the backend and the Elm-Architecture on the frontend.
  • It reuses projections from the backend in the update function of the elmish app. The backend is sending domain events to the frontend and the (Elm-)model is updated with the help of projections defined in the backend (on all clients that are connected via websockets).
  • It shows an easy way of implementing "Whatif"-Scenarios, i.e. scenarios that enable the user try out different actions. When the user is happy with the result the system sends a batch of commands to the server. When "Whatif-Mode" is enabled the client reuses not only the projections but also the domain behaviour defined on the server to create the events needed by the update function. The potential commands are also stored.
  • It uses the awesome Fulma library for styling
  • It has BDD Style tests that show how nice the behaviour of Event-Sourced systems can be tested.
  • Websockets with Elmish/Suave


Up to now there is no working version available online. Any help would be appreciated. If you want to try it locally, please run the fixtures (see Demo Data section below). Otherwise you will not be able to login or see any kind of data.


This project consists of 6 dotnetcore subprojects

  • Domain - Message-based CQRS implementation of the Domain of a ConferencePlanner.
  • Domain.Tests - BDD-Style Tests for the Domain
  • Client - Fable Project that uses the Elm-Architecture (with Fable-Elmish). It reuses the projections of the Domain project. Furthermore it and can also reuse the behaviour of the Domain (when switched to WhatIf-Mode)
  • Server - A Suave Webserver that allows the Client to connect via Websockets.
  • Infrastructure - This is where all the backend infrastructure is implemented. It contains a simple (file based) event store, command and query handlers and the types that hold everything together. Most of the infrastructure is implemented asynchronously with the help of F# awesome Mailbox Processors
  • Support - A simple project to fill the EventStore with some initial values.


Development mode

This development stack is designed to be used with minimal tooling. An instance of Visual Studio Code together with the excellent Ionide plugin should be enough.

Start the development mode with:

> build.cmd run // on windows
$ ./ run // on unix

This will start Suave on port 8085 and the webpack-dev-server on port 8080. Then it will open localhost:8080 in your browser.


NOTE Currently there is a bug that might prevent Fable and the server to be started in parallel.

If this is happening:

  • open a terminal
  • go to src/Server
  • run dotnet run
  • open another terminal
  • go to src/Client
  • run dotnet fable yarn-run


With FAKE (does a full dotnet restore etc.)

> build.cmd RunTests // on windows
$ ./ RunTests // on unix

On the CLI (without building everything) in src/Domain.Tests:

> dotnet test

or in watch mode

> dotnet watch test

You can now edit files in src/Domain or src/Domain.Tests and recompile + testing will be triggered automatically.

Demo Data

If you want prefill the conference Event-Store with some demo data you can run:

> build.cmd RunFixtures // on windows
$ ./ RunFixtures // on unix

The events will be written to src/Server/conference_eventstore.json

Currently you do want this, because there is no way to add abstracts or organizers.

Plans for the future

From the top of my head. If anyone wants to chip in, feel welcome.


  • make use of Azure to deploy the application


  • extract the project into its own repository and make it a bit more production ready :D
  • implement at least one different event store implementation (e.g. SQLite or Azure something something)
  • implement projections that can send notifications


  • implement a proper autohrization system


  • build an actual Conference Planner

Known Issues

Getting rid of errors in chrome/firefox

  • Either comment out the lines in App.fs:
|> Program.withDebugger
  • Or install the Redux DevTools as a Chrome/Firefox Extensions (recommended) Only one error remains, when visiting the WebApp the first time.