Htmx/htmlact web development approach

People who are looking for more lightweight alternatives – and want to do web programming without bothering too much about front end insanity can have a look at htmlact (yes indeed: sending HTML over fetch, web programming excels at running in circles).

The front JavaScript for that CRUD webapp comes out at 132Ko uncompressed without even trying to tweak anything.

15 Likes

Really cool, I guess it’s similar to Phoenix liveview as well. Thanks for sharing!

That’s what I have been told but formally, as mentioned in the docs, the inspiration is htmx.

6 Likes

Very interesting, did you write somewhere about how it compares to htmx?

2 Likes

Dang it @dbuenzli one day you’ll run out of letters and need to come up with an actual name for your libraries.

15 Likes

FWIW, one can use htmx quite easily via e.g. dream. I’ve been doing just that for a few months now, with very pleasant results.

3 Likes

Same, I’ve been hacking on a side project with Dream and htmx (SQLite for persistence). It’s been really nice. EDIT: thought I’d mention my fronted JS total size (no compression or bundling) is 36 KB.

5 Likes

Not really.

As far as I can remember I liked the ideas but found their execution to be a bit lacking, sometimes ad-hoc in their attribute DSL, focusing more on the show off to convince single page application proponents of the approach than on a clear conceptual model (which htmlact tries to detail in the manual here).

Two other things that come to mind are:

  1. AFAIR their examples relied a lot on unique id attributes for targeting request results. Unless you find a principled and automated way to generate these that’s not compositional and brittle. In htmlact I extended the CSS selector syntax to allow to address your ancestors (peace be upon them). That’s more compositional but now you become sensitive to structural changes in your markup – pick your poison[1].
  2. I’m no longer sure about that, i.e. don’t take my word for it, but I think their DSL allowed to spread the definition of an interaction among many elements which made it more difficult to understand what is happening. In htmlact all attributes defining the effects of an interaction are always located on a single element, the element that performs the request.

Finally when things go wrong I prefer to have to understand 700 lines of ml rather than 2800 lines of JavaScript (note that they likely have better legacy browser support and more functionality).

In any case there’s a long list of todos in htmlact and it likely needs one or two more design rounds before getting to something decent – if that’s even remotely possible on the web.

Mind you I tried to use three letters once, but the whole experience turned out to be extremely unpleasant :–)


  1. Using unique ids reifed in an OCaml EDSL could be a better idea. ↩︎

10 Likes

Is htmx as expressive as React? Seems like it can’t be, right?

1 Like

I don’t know which react you are talking about but I suspect you can encode a Turing machine in the three of them.

A good way of seing the approach is to relate it to a form of X11, except your widgets are even more broken, because on the web everything truly is (and given the various actors that define it, that’s not going to change – there’s a conflict of interest, too many people would get out of business if you brought sanity in that world).

In any case nothing new under the sun here. People have been doing that for a long as xmlhttprequest has existed except the hysterical, fashion ridden, self-sufficient web development world seems to have forgotten about it. However, to be fair, a few new front-end technologies like CSS animations, makes it easier nowadays to put the approach on par with a bloat of JavaScript on your client.

1 Like

@cemerick, @yawaramin, @dbuenzli, and others who’ve used htmx/hc with OCaml back-end: what is your experience with templating? It seems that htmx/hc puts high requirements on a flexible HTML templating/DSL. What did you choose and is it working out for you?

I’m using OCaml and an absolutely trivial HTML generation library. If you want to see a real world example head to the *_html.{ml,mli} files in this directory (more on the structure found there here)

Works quite well for me but I’d say the problem is not really templating it’s rather non-brittle URL management. For that I use this module which while I’m not entirely convinced by it yet, allows me to type them and avoid the stringly unchecked dependendencies so characteristic of the web development world.

4 Likes

Mind you I tried to use three letters once, but the whole experience turned out to be extremely unpleasant :–)

@bluddy rel is three letters long (one more than hc); so it is already an improvement, right? :wink:

1 Like

omg, he’s incredible firm with unicode…

Yeah, you’re right on that point.

I’m using tyxml for 99% of my HTML generation, specifically its jsx ppx. I am judicious about keeping the main logics of the project in OCaml proper; .re files exist exclusively to hold markup. The end result is a very pleasant environment IMO. In the end, I dearly wish there was a way to get actual HTML syntax into .ml files (I am no fan of reason syntax outside of jsx, and I suspect the sorta-legacy jsx toolchain leftover from reasonml will end up being a tech risk over time), but as things stand, it’s the best option I’ve found.

5 Likes

Slightly off-topic question, but I suppose you consider the tyxml ppx (which has exactly the same expressivity as the jsx version) too heavy ?

I’m just using Dream’s ‘built-in’ templating, ‘Embedded ML (.eml)’, it works reasonably well–each template or partial is just a function that you define to take some arguments and return some markup. It even auto-escapes to prevent injection attacks. E.g.,

let card name =
  <div class="card"><%s name %></div>

There are a couple of tricks to be aware of with the EML syntax but in general it works well.

3 Likes

For the little webdev I do (internal tools mostly for myself), I’ve also been using server side html generation, with my own wheels tools and a bit of htmx.

Here’s an excerpt from a personal project, with my own httpd and html combinators; it adds a root to handle /thy/<some string>:


let h_thy (self:state) : unit =
  H.add_route_handler self.server
    H.Route.(exact "thy" @/ string_urlencoded @/ return) @@ fun thy_name req ->
  let@ () = top_wrap_ req in
  let thy = Idx.find_thy self.st.idx thy_name in
  let res =
    let open Html in
    [
      div[cls "container"][
        h3[][txtf "Theory %s" thy_name];
        Thy_file.to_html thy;
        div [
          "hx-trigger", "load";
          "hx-get", (spf "/eval/%s" @@ H.Util.percent_encode thy_name);
          "hx-swap", "innerHtml"] [
          span[cls "htmx-indicator"; A.id "ind"][
            txt "[evaluating…]";
          ]
        ];
      ]
    ]
  in
  reply_page ~title:(spf "theory %s" thy_name) req res
4 Likes

I would probably switch over to Dream’s EML, if ocamllsp/vscode supported it fully. (I know that’s a tall order.) The last I heard on this front was @tmattio’s comment here; tl;dr: don’t hold your breath. :upside_down_face:

I never know what people mean by “heavy” :slight_smile:

But yes, I did use the regular tyxml ppx for a while when I first started using dream, and have tried it 2-3 times since. It’s totally fine, the language support is great (again, not a fan of reason as a whole, and ocamllsp sees everything it needs to within the ppx expressions), but editing HTML within strings interleaved with not-strings is really very cumbersome. Doubly so when copy-pasting HTML snippets from e.g. design tools, which then need to be laboriously split into N strings to accommodate the necessary antiquotations, etc.

I think I suggested on discord some weeks back an addition to the ppx to support interpolation of values via some notation within the HTML, e.g. instead of:

let page =
  let title = Html.txt "title" in
  let eid = "summary" in
  [%html "<h1>" [ title ] "</h1><p id=" eid ">content</p>"]

Something like this would IMO yield something at least as pleasant to edit as EML or JSX:

let page =
  let title = Html.txt "title" in
  let eid = "summary" in
  [%html {|<h1>{[title]}</h1><p id={eid}>content</p>|}]

…and then for bonus points, it should be relatively straightforward to convince vscode/merlin to syntax-highlight and format the now-unitary %html strings. It’s on my TODO list, though tbh I probably won’t be panic-motivated until refmt breaks (more).