Introducing Giraffe.Htmx

Posted by Daniel on Tuesday, November 9, 2021 at 4:06 pm

Categorized under , ,

Giraffe is a library that sits atop ASP.NET Core and allows developers to build web applications in a functional style; dotnet new giraffe is literally my starting point when I begin a new web application project. (Rather than write three more sentences filled with effusive praise, I'll just leave it at that; it's great.) It also provides a view engine (that builds upon Suave's “experimental” view engine) which uses an F# DSL to define HTML in a strongly-typed way. It has been incredibly efficient for a while, but with .NET's work over the past two releases at improving performance, and Giraffe's adoption of those techniques, it is lightning fast.

htmx is a library that brings interactivity to HTML through the use of attributes and HTTP headers. Whereas projects like Vue, Angular, and React prescribe completely different programming paradigms than traditional web development, htmx provides partial-page-swapping and progressive enhancement within straight HTML. This brings a lot of the benefits of the SPA architecture to vanilla HTML, without requiring a completely different paradigm than the one we have used on the web for 30 years. In practice, this greatly reduces the complexity required to produce an interactive web application.

The Giraffe.Htmx project provides a bridge between these two libraries. The project consists of two different NuGut packages.

  • Giraffe.Htmx provides extensions to Giraffe (and its exposure of ASP.NET Core's HttpContext) that expose the request headers which htmx uses, and provides Giraffe-style HttpHandlers to set htmx's recognized response headers. The request headers are exposed as Options, and if present, are converted to the expected type. Response headers can be set in a similar way (i.e., passing true instead of "true" for a boolean header).
  let myHandler : HttpHander =
    fun next ctx ->
      match ctx.Request.HxPrompt with
      | Some prompt -> ... // do something with the text the user provided
      | None -> ... // the user provided no text (likely was not even prompted)
      ...
  • Giraffe.ViewEngine.Htmx extends Giraffe's view engine with attribute functions (ex. _hxBoost equates to hx-boost="true") to generate HTML with htmx attributes. As with the headers, the values for each attribute are expected in their strongly-typed form, and the library handles the necessary string conversion. For attributes that have a defined set of values, there are also modules that provide those values; the example below demonstrates both the attributes and the HxTrigger module.
  let autoLoad =
    div [ _hxGet "/this/endpoint"; _hxTrigger HxTrigger.Load ] [ str "Loading..." ]  

Head over to the project site for NuGet links and more examples!

p.s. As of this writing, the current (and only) version of this library is at v0.9.1. Both libraries should be ready for development use. For Giraffe.ViewEngine.Htmx, I intend to write helpers for hx-headers and hx-vals that will allow a list of string * string tuples to be passed. I also need to write READMEs for both NuGet packages. Once those are done, this will be v1-ready.