Designing Hypermedia-Driven Applications - Intro

Aug. 13, 2024

Working on hypermedia-driven applications (HDAs) for some time now it has become my preferred way of building applications - if the application allows it (1). The biggest difference compared to the seemingly standard way of building frontends using a Javascript framework is a rather philosophical one: the DOM is your application and its source of truth, not just your rendering engine.

Let me explain.

UI = f(state)

When it comes to frontend development I’m coming mostly from a React background. In React, the user interface is understood as a function of the application state, or short UI = f(state) (i.e. this post by Dan Abramov).

In a classic client-side rendered React application, the application state is often populated using data served by backend via a JSON API. The frontend is sometimes colloquially also called the “client”, especially when distinguishing it from the server. In this context, the browser - which is actually an HTML client in itself - is degraded to an elaborate rendering engine (2).

Embracing the browser

Irrespective of your views on React or Javascript frameworks, it’s hard to argue that the UI equation UI = f(state) is a very principled approach to building user interfaces. I guess this is a major reason for the success and scale of the React ecosystem.

In contrast, the main idea in HDAs is that the hypermedia (aka the DOM) holds the entire applications state and drives it forward (i.e. defines how you can interact with it). Interactions are limited to a predefined set, for example navigating to a new page by clicking a link or submitting a form by pressing enter in a form field. These limitations have the advantage that a single client - the browser - can interpret all HDAs.

In comparison to building React applications, building HDAs feels a bit like the wild west, where you can invent your own rules and might be surprised by unforeseen engineering challenges or browser quirks around the next corner. You’ll need more elaborate patterns in the backend and sometimes you’ll also want to extend the browser, to give you richer interactions.

Still, when done with the right mindset, HDAs can be highly effective, especially in terms of developer productivity. One of the main reasons for this is Locality of Behavior, another term coined by Carson Gross. Locality of Behavior applies at many scales of a design and is a quality that seems to make systems easier to understand and change.

In this series of posts, I’ll try to discuss some techniques I use when developing HDAs. For interactivity involving the server, I’ll be focusing on HTMX, which arguably has created a renaissance of HDAs. For client-side interactivity the possibilities are numerous, so I’ll try to discuss some techniques and libraries I found useful in the past.

My goal is to build frontends that are thin in the logic they implement, but rich in their interactivity.

Footnotes


  1. (1) Read the excellent essay by Carson Gross, the author and CEO of HTMX, to understand where HDAs can (and should) be used. Actually, have a look at all the essays, there’s good stuff in there. 

  2. (2) Server-side rendering (SSR) does not really change the picture here, since it mostly about moving rendering of HTML from the client to the server - hence the name. React Server Components (RSCs) are a completely different beast, as they conceptually remove the application level separation between the client and the server. There is still a separation of course, because you cannot just make the network disappear, but the developer now gets to use exactly the same tools on the backend and the frontend. In contrast to client-side components, RSCs get access to resources that are normally associated with the server-side only (i.e. databases).