Hypermedia Systems

Hypermedia Systems is a book written by Carson Gross, Adam Stepinski and Deniz Akşimşek.

It describes the benefits of creating hypermedia-driven applications.

Here are my notes and summary.

The road to Hypermedia Systems

Tim Berners-Lee used the term hypermedia in the first website in the world.

Clicking on a link allows to interact with the media in a manner beyond reading from start to end.

Browsers added the form element in the early 90s, standardized in HTML 2.0.

Hypermedia controls — links and forms — gave rise to a new way to build and distribute software based on the hypermedia notion.

In 2000, Roy Fielding further described this application architecture.

The book’s authors use the expression hypermedia system to describe a system architecture:

  • whose building blocks are:
    • hypertext/hypermedia (e.g. HTML, XML)
    • network protocols (e.g. HTTP)
    • servers
    • clients (e.g. web browsers)
  • adhering to the principles described by Roy Fielding

Rise of the SPA

In 2005, the XMLHttpRequest API became the key technology behind the Ajax revolution.

Ajax closed the gap between the experiences users can get from a desktop and a web application.

Richer applications became so large that people started building infrastructures to manage them.

These JavaScript Web Applications became known as SPAs (Single Page Applications).

SPAs have become the default in our industry:

  • abandoning the notion of page
  • moving to a JavaScript model living in memory
  • exchanging micro transactions over JSON

Tight coupling of JSON APIs and UIs

SPAs interact with a server via JSON API calls.

The JavaScript must have intimate knowledge of the data to transform it into HTML:

  • if the format of the returned JSON is modified
  • then the UI code will almost always have to be modified

As a result, the API and the UI are tightly coupled.

And because the UI is constantly in flux, API endpoints will end up being always tweaked to please UI needs.

Your likely options will be API churn or GraphQL security-related issues.

The flexibility of Hypermedia APIs

An alternative approach consists of returning HTML responses.

Response Type HTML JSON
Response
<html lang="en">
<body>
    <h1>Joe Smith</h1>
    <div>
        <div>Email: joe@example.bar</div>
        <div>Status: Archived</div>
    </div>
    <p>
        <a href="/contacts/42/unarchive">Unarchive</a>
    </p>
</body>
</html>
{
  "name": "Joe Smith",
  "email": "joe@example.org",
  "status": "Archived"
}
State of the application Encoded in the response Not encoded in the response
As state changes The browser needs to know:
  • an entry point URL
  • how to render HTML
The JavaScript needs to know:
  • an API entry point
  • about the internal structure and meaning of the data
  • how the fields are structured and named
  • how the fields relate to one another
  • how to update the local data with this new data
  • how to render this data to the browser
  • what additional API end points can be called with this data

So when a new feature is shipped:

  • display and what can/cannot be done are self-contained in HTML responses
  • the browser simply renders the new HTML (no extra documentation required)
  • hypermedia APIs do not have the (breaking) changes headaches that JSON Data APIs do

The JSON response is smaller, but the flexibility of the HTML response is worth the trade-off.

This flexibility allows to build refactorable hypermedia APIs optimized to particular UI needs.

Extending HTML

Some JavaScript libraries have been returning HTML over the wire:

The main idea is to augment HTML by addressing its core limitations:

  • allow any element to issue a request, not just <a> and <form>
  • allow any event to trigger a request, not just click and submit
  • allow any HTTP method, not just GET and POST
  • allow any part of the screen to be replaceable (transclusion), not just the entire screen

Build sophisticated modern web applications

Augmenting HTML allows to reach a level of interactivity that most web developers would assume requires a SPA framework.

The book showcases this by using htmx to improve a Flask web application.

I developed a barebones Django version of it to experiment with htmx patterns:

Two things allow more readable/smaller code and prevent spaghetti code:

Other things to note:

  • the code uses template inclusions rather than components
  • htmx leaves room for progressive enhancement
  • you can have one backend for many hypermedia formats
  • you can leverage the cache behaviour of HTTP responses

The future could be even brighter.

Where do you want to spend your complexity budget?

Software systems are intrinsically more complex than physical systems and tend to be append-only.

RPC-like APIs and JS-heavy architectures add to that complexity:

  • tooling (Webpack, Vite, Rollup, ESbuild, etc.)
  • maintenance of a npm toolchain in parallel with a backend toolchain
  • client-side routing
  • new abstraction over DOM manipulation
  • server-side HTML generation (or rendering)
  • attaching dynamic behavior to server-rendered tags on load (hydration)
  • scattering of components across multiple repositories
  • performance issues
  • frontend and backend teams disagreeing over JSON payload format
  • etc.

When they’re a good fit, hypermedia concepts can simplify system architectures a lot.

You have to decide what matters and where you want to spend your complexity budget.

Avant HTML form serialization Après Using an SDL fight stick with RPCS3 on ARM64 Mac

A Kemar Joint