How to Build a Fullstack Webapp with F#
Date: 2024-06-19 | create | tech | fsharp |
I like to build side projects and F# is my favorite programming language so I end up building a lot of projects with F#. I also like to share my Creations as a way to crystalize my knowledge and get feedback from the broader community. Together this means I build a lot of projects and share a lot of things about F#.
So I was surprised when I got messages asking me for tutorials on how to build fullstack web apps with F#.
"I already do this!" I thought.
But then I realized that while I've covered a lot of domains over the years it's all scattered about. There is no one-stop shop to help you go from zero to production web app. The closest thing I have is the guides section of CloudSeed (my F# project boilerplate).
So in this post I'm going to create a paved road for going from no app to a working fullstack web app built with F#. This is more of a runbook than a detailed technical guide - it will walk through the high level decisions you need to make, provide some suggestions, then point you to the more detailed guides that already exist for implementation based on those decisions.
Sections:
- Why build webapps with F#? - Why you should consider using F# to build your next web app
- Choosing a system design - Thoughts on system designs and how that affects your tech choices
- Build a backend with F# - Build a solid core for your app logic
- Build a frontend - Provide ways to interact with that app
- Real world examples - Some inspiration
Why build webapps with F#?
I like F# because it feels like a language that has learned from the mistakes of others. It tries to be simple while providing tools to be correct. It tries to push you into the pit of success while allowing you to do less "correct" things should you need to. It tries new, better ways of doing things while still interoperating with existing ecosystems.
All in all it feels like a language that is trying to be better even if that's different from the way other languages do things. In many ways it feels like it's striving (and largely succeeding) at being what a modern language should be - taking the lessons from the last 50 years of programming and making a language to solve for those.
It is like a nice pen or keyboard or rain jacket - there are other ones out there that work fine but this one is better in so many ways. Not everyone will appreciate these but I do.
Some concrete things I really like about F#:
- Type system - Its type system is powerful, concise, and precise - it's like Rust w/o the boilerplate or TypeScript but doesn't lie
- Ergonomic - Very nice utilities for piping, list operations, and railroading
- Pragmatic - Functional-first but ability to fallback to OO if you want and runs on dotnet so you can also access all of C#'s libraries (very big ecosystem)
I kind of think of it like - what if there was a language with the simplicity of Python, the type system of Rust / TS, and the performance of Go? F# does that.
If you're still not sold on F# then this post may not be for you. If you're still on the fence I recommend the "Why use F#?" series - it's what convinced me to take my first steps.
Related posts:
- 5 Reasons F# is a great Python alternative for scripting, side projects, and enterprise applications
- Why F# is a fun programming language
- How I got interested in F#
Choosing a System Design
At this point I'm going to assume that you're at least a little bit interested in building a fullstack webapp with F#. We'll get there but first we need a general idea of what you're going to build and how before I can give more specific recommendations.
This may seem boring and not useful but I like the saying "weeks of coding saved me hours of planning". Here I am going to waste minutes to save you days.
You do not need to plan down to the code logic. I'm just asking you to think about the general structure of your app so that you can set off in a reasonable direction instead of running around in circles.
My general philosophy for building webapps these days is the HAM Stack. This is a web-first philosophy that provides a rough outline for what most solid webapps look like - pulling from patterns and best practices from my own experience building real-world software and the experience of others at small and large scale, for enterprise and side projects.
The idea is simple:
- Hypermedia
- on A Modulith
Hypermedia - The world is web-first and will continue to be more web as more people get connected and more apps are more interconnected. Yes devices are cool and native experiences are great but we are moving towards a world where build once, run anywhere makes more and more sense. The web is the best way we've found to do this so I would not bet against the web.
on A Modulith - Microservices were fun and can make sense for hyperscale companies. You are not a hyperscale company. If you try to build like a hyperscale company before you hyperscale you will bury yourself in overhead and never reach hyperscale (or any scale for that matter). Moduliths are an excellent balance of simplicity, maintainability, and performance - this makes it a 3S for building apps in my book.
Note that you can build most webapps with this stack. It is not prescriptive about the tech you choose or most of the structure of your app. Instead it provides suggestions / guardrails based on what fellow builders have found to work / not work across many project types.
For example, all the following would fit nicely into this philosophy:
- A standard Multi-Page Application using HTML Templates
- A frontend running SvelteKit and a backend running F# (this is how I used to build my apps)
- A server-side rendered HTMX app (this is how I currently like to build things)
If you disagree with this philosophy / are trying to build something that does not run on the web or fit into this philosophy then this guide may not be for you.
If you are still interested then read on and we'll get you started.
Related posts:
- The HAM Stack - A Simple Scalable Tech Stack for building modern web apps fast and cheap
- CloudSeed Quickstart (Fullstack F# app in 10 minutes)
- Software Monoliths for Scale
Build a Backend with F#
Okay so you still want to build a fullstack web app with F# - let's get started.
Regardless of whether you are choosing to build your frontend with F# or instead serving it with a separate app - we're going to need a place to put our core app logic. You've decided to build with F# so this basically means you'll need an F# backend no matter which way you go.
To build a backend with F# we mostly need two things:
- Web API - A way to receive incoming web requests and respond w data
- Data Access - A way to CRUD our data (cause any real app doing real things needs data)
Building an F# Web API
These days I mostly build my web APIs with Giraffe. There are other good options out there but I stick with Giraffe because it's solid, still gets updated, and has a lot of good features.
I have several guides for getting started with F# / Giraffe:
For a survey of other options:
Data Access with F#
Okay now that you have a way to receive and respond to requests we're going to need a way to CRUD data. You may think this is not important but I would argue 80%+ of software engineering is just CRUD so choosing a good method here will make your life easier in the long run.
I personally like to use F# with Entity Framework as an ORM because I think it works well for the 80p case, has great documentation, and is always being updated by the C# folks. For migrations I like to use DBUp because I like a little bit more control over my db versioning.
That said there are many other good ways to do this:
Build a frontend with F#
Okay so now you should have a backend ready to go. This is usually not enough though unless you're building an API-only thing but really no real-world app is just an API there's almost always some frontend even if it's only to help the creator admin the thing.
If you've decided to use something that is not F# to build your frontend -> go find the guides for that.
If you decided to use F# then here's some things you can try:
- HTML Templates - Type-safe Server-side HTML Rendering with F# / Giraffe
- HTML DSLs - Server-side HTML Rendering with F# and Giraffe.ViewEngine
- F# + HTMX - Simple Interactive Islands with F# and HTMX
Personally I've been having a lot of fun with the HTML DSLs building MPAs then sprinkling HTMX in for more dynamic interactions where necessary.
Related posts:
- Why you should choose HTMX for your next web-based side project - and ditch the crufty MPA and complex SPA
- Why I'm moving from SvelteKit to F#
That said there are a lot of other ways to do build frontends with F# - Fable, Bolero, Blazor etc. I haven't done much with these myself but they're worth looking into if you're intereested.
Real World Examples
So that's the crash course for the things you'll need to do to build your first web app with F#. But a lot of this might be hard to conceptualize into how it fits together so here I'm going to leave you off with a few examples of apps using these paradigms.
- How I built this site - Build a Simple Markdown Blog with F# / Giraffe
- How I host this site - How I host my Server-Side-Rendered F# site on Google Cloud for less than $1 per month
- TravelMap - a site that lets you plot locations on a map, built with F#, HTMX, and Alpine
Next
I know this post is a bit of a whirlwind of information but hopefully it helps give you a little bit of direction into the kinds of things you'll need to build and how to learn more about each of them. At the end of the day everyone likes to build things a little bit differently so this is just how I like to build things - if you like to build different that's okay too.
If you want to get started building a fullstack webapp with F# quickly, I've compiled all the techniques / technologies I like to build with into a single boilerplate - CloudSeed. This is how I start all of my projects these days - I clone it, get a ready-made webapp with data access and containerization, then start building on it.
Q: What kinds of things are you trying to build with F#? What's been stopping you?
If you liked this post you might also like:
Want more like this?
The best / easiest way to support my work is by subscribing for future updates and sharing with your network.