Getting Started with Suave

This guide will help you install Suave and create your first web server.

Prerequisites

  • .NET 8 or later
  • F# 4.7 or later
  • A code editor (VS Code, Visual Studio, or similar)

Installation

Step 1: Create a new F# project

dotnet new console -lang F# -n MyWebServer
cd MyWebServer

Step 2: Add Suave via NuGet

dotnet add package Suave

Hello World

Replace the contents of Program.fs with:

open Suave
open Suave.Successful

let app = OK "Hello, Suave!"

startWebServer defaultConfig app

Run your server:

dotnet run

Open your browser to http://localhost:8080 and you should see "Hello, Suave!"

JSON Response

Return a typed record as JSON with Suave.Json.toJson. Install the package first:

dotnet add package Suave.Json

toJson lives in the separate Suave.Json NuGet package — it is not part of core Suave.

open System.Runtime.Serialization
open Suave
open Suave.Operators
open Suave.Writers
open Suave.Json

[<DataContract>]
type Person =
  { [<field: DataMember(Name = "name")>] name : string
    [<field: DataMember(Name = "age")>]  age  : int }

let person = { name = "Alice"; age = 30 }

// toJson : 'T -> byte[]  — use Successful.ok (bytes), not OK (string)
let app =
  toJson person
  |> Successful.ok
  >=> setMimeType "application/json"

startWebServer defaultConfig app

For request/response mapping with mapJson, see the JSON recipe.

Basic Routing

Handle different URLs:

open Suave
open Suave.Filters
open Suave.Operators
open Suave.Successful
open Suave.RequestErrors

let app =
  choose [
    path "/" >=> OK "Welcome!"
    path "/about" >=> OK "About page"
    path "/contact" >=> OK "Contact us"
    NOT_FOUND "Page not found"
  ]

startWebServer defaultConfig app

→ Learn more about routing

Handling Requests

Access request data:

open Suave
open Suave.Filters
open Suave.Operators

let app =
  request (fun req ->
    let method = req.method
    let url = req.url
    sprintf "You made a %s request to %s" (string method) (string url)
    |> Successful.OK)

startWebServer defaultConfig app

Query Parameters

Parse query strings:

open Suave
open Suave.Filters
open Suave.Operators
open Suave.Successful

let app =
  request (fun req ->
    match req.queryParam "name" with
    | Choice1Of2 name -> OK (sprintf "Hello, %s!" name)
    | Choice2Of2 _ -> OK "No name provided")

startWebServer defaultConfig app

Try: http://localhost:8080?name=World

POST Data & Forms

Handle form submissions:

open Suave
open Suave.Filters
open Suave.Operators
open Suave.Successful

let app =
  choose [
    POST >=> request (fun req ->
      match req.formData "message" with
      | Choice1Of2 message -> OK (sprintf "Received: %s" message)
      | Choice2Of2 _ -> OK "No message")
    
    GET >=> OK """
      <form method="POST">
        <input name="message">
        <button>Send</button>
      </form>"""
  ]

startWebServer defaultConfig app

Serving Static Files

Serve files from a directory:

open Suave
open Suave.Filters
open Suave.Operators
open Suave.Files

let app =
  choose [
    browseHome
    Files.file "404.html"
  ]

let config = {
  defaultConfig with
    homeFolder = Some (System.IO.Path.GetFullPath("public"))
}

startWebServer config app

Configuration

Customize your server:

open Suave
open Suave.Successful

let app = OK "Hello"

let config = {
  defaultConfig with
    bindings = [ HttpBinding.createSimple HTTP "127.0.0.1" 3000 ]
    homeFolder = Some "public"
    hideHeader = false
}

startWebServer config app

Next Steps

Troubleshooting

Port already in use

If port 8080 is already in use, change it in the config:

open Suave
open Suave.Successful

let app = OK "Hello"

let config = {
  defaultConfig with
    bindings = [ HttpBinding.createSimple HTTP "127.0.0.1" 3000 ]
}

startWebServer config app

Changes not showing

Stop the server (Ctrl+C) and rebuild:

dotnet clean
dotnet build
dotnet run