Fable.io from Scratch — Part 1

In this series of articles, we will look at getting started with Fable from an empty directory to get a better understanding of how the stack works. It is assumed that you know what Fable is and have a desire to learn more about how the stack works. Part 1 covers Paket.

DISCLAIMER: This is the hard way of starting a fable project. It is intended for people to learn more about the stack Fable is built on. For a better quick start experience using a template with all of this configured for you, please check out the Getting Started with Fable and Fable Elmish article.

Visual Studio Code showing paket.dependencies


node — Needed to execute JavaScript code
yarn — Used for dependencies on the JavaScript side
.NET Core SDK — Used for project management
Ionide Family of Plugins — Not required, but strongly recommended to improve developer experience.

The rest of the prerequisites will be downloaded along the way. So let’s dive in.

Creating the Directories

First create a new directory where you want the application to live.

mkdir fable-from-scratch

Next, create an empty folder called .paket which will be explained below.

cd fable-from-scratch
mkdir ./.paket

What is the .paket folder we just created? The package manager we will be using for our .NET dependencies is Paket. Using this makes sense for a number of reasons, but the biggest benefit is the paket.lock file. This ensures that even after checking into source control, when consumers restore dependencies, they end up with tested dependencies instead of just whatever the latest and greatest is that could have breaking changes.

Paket keeps it’s executable files in the .paket directory which we created above and need to bootstrap the app. This is a common pattern with apps that use Paket, so I like to add a relative path to my path environment variable. I do this by editing my PowerShell profile on Windows and adding the following code:

$env:Path = $env:Path + ";./.paket"

This step isn’t required, but it reduces keystrokes by not having to type ./.paket/paket.exe every time I want to use the paket cli. You can add this as an environment variable however you see fit, or not at all. This is more of a personal convenience.

On macOS you need to prefix the command with mono like this:
mono ./.paket/paket.exe

Bootstrapping Paket

Download the paket.bootstrapper.exe file and then rename it to paket.exe and copy it into the .paket folder. This enables “magic mode” which you can read about very quickly in the paket documentation.

Creating the Project

After this we need a new dotnet project to work with. To do that execute the following commands.

Windows or macOS

dotnet new console -lang f#

Switch from NuGet to Paket

By default the project generated with “dotnet new” uses NuGet for package management. Paket offers an easy way to remedy this. Just execute the following command from our project directory.

./.paket/paket.exe convert-from-nuget

Remember on macOS you need to add “mono” in the front of the command. The above command tells paket to convert from NuGet to Paket. This will create the following files.

packages folder - This folder is empty now, but will be the future home of any dependencies you download via paket.
paket.references - This file will be in the root of your project.  It holds the references used by the adjacent project (.fsproj file).
paket.dependencies - This file will be in the root of your project and is where paket manages the list of your direct dependencies.  This file can be manipulated manually or you can use commands like paket add and paket remove to manipulate the file for you.

Adding Dependencies

Let’s search for fable related packages.

./.paket/paket.exe find-packages searchtext Fable

which outputs:

Paket version 5.1.7
- Average Request Time: 208 milliseconds
- Number of Requests: 2
- Runtime: 1 second

I highlighted 2 packages above. We will be installing these packages. The first package we will install with paket add the other we will edit the paket.dependencies file directly. Let’s go ahead and add Fable.Core using the paket cli. We will specify the project location so the paket.references file get’s updated as well.

./.paket/paket.exe add nuget Fable.Core project ./fable-from-scratch.fsproj

At this point notice the new entry in the paket.dependencies file. It should look exactly like this on Windows:

source https://api.nuget.org/v3/index.json
nuget Fable.Core
nuget FSharp.Core >= 4.1.0
nuget FSharp.NET.Sdk >= 1.0.0

Next, add a new dependency to the end of the file like this:

source https://api.nuget.org/v3/index.json
nuget Fable.Core
nuget FSharp.Core >= 4.1.0
nuget FSharp.NET.Sdk >= 1.0.0
nuget Fable.Import.Browser

Save the file. In the file above, we are telling Paket that a project somewhere has a dependency on Fable.Import.Browser, but we need to also update paket.references so that Paket knows we want to use it in our project. To do that we simply add Fable.Import.Browser to paket.references. It should look like the following.


When making changes directly to the files like this, the changes do not get detected automatically. For this we need to install the newly added NuGet package.

When making changes directly to the file like this, the changes do not get detected automatically. For this we need to install the newly added NuGet package.

./.paket/paket.exe install

At this point Paket has installed all dependencies into the packages folder and updated the paket.lock file to lock the dependencies to the current installed versions. The paket install command also added a restore target to the .fsproj file. This allows you to restore paket dependencies by simply doing a dotnet restore.

Updating Packages

If you ever want to check for newer versions of components, you can simply run:

./.paket/paket.exe outdated

If you need to update dependencies, simply run:

./.paket.exe update


  • How to use Paket for your Fable/.NET dependencies.
  • You can use the standard console application template from dotnet cli to bootstrap the app

In the next part we will look at getting up and running with yarn and webpack.