Skip to main content

Exploring HTMX and HATEOAS in Modern Web Development

Front-end Development
Back-end Development

One of my main goals this year has been to explore new web development technologies. Along the way, I came across a lightweight JavaScript library called HTMX, which immediately piqued my interest. What deepened that interest was its close alignment with a development philosophy known as HATEOAS — short for Hypermedia As The Engine Of Application State.

This philosophy not only shaped my understanding of HTMX, but also challenged many assumptions I’ve carried as a React developer.

What Is HATEOAS?

HATEOAS builds on the widely adopted REST (Representational State Transfer) architectural style. REST promotes stateless, uniform communication between clients and servers. HATEOAS extends this by insisting that clients navigate an application using links and forms included in the server’s responses, rather than constructing URLs or hardcoding workflows.

In other words, the server doesn’t just return data — it also tells the client what actions are possible in the current context.

Example (Simplified)

{
  "id": 101,
  "user": "you",
  "caption": "My dog!",
  "links": [
    { "rel": "edit", "href": "/posts/101/edit", "method": "PUT" },
    { "rel": "delete", "href": "/posts/101", "method": "DELETE" },
    { "rel": "comment", "href": "/posts/101/comments", "method": "POST" }
  ]
}

The client doesn’t need to guess how to edit or delete the post — it just follows the links provided.

How This Differs from a Typical React App

In traditional React applications (and many other front-end frameworks), the client determines:

  • What actions a user is allowed to take.
  • What buttons or components should be rendered.
  • What URLs to hit when performing an action.

This often results in duplicated business logic. For example, the frontend might check whether a user is the creator of a post to determine whether to show the “Edit” button, like so:

if (currentUser.id === post.user.id) {
  showEditButton();
}

If the client decides to perform an edit, it constructs the URL:

fetch(`/posts/${post.id}/edit`, { method: 'PUT', body: updatedContent });

This setup can work — but it hardcodes assumptions about user permissions, URL structures, and application rules.

Real-World Scenario: Instagram

Take Instagram. Users can post photos with captions, but only the creator can edit or delete them. Here’s how this differs in two paradigms:

In a React App:

  • The frontend checks if the current user matches the post’s creator.
  • It builds URLs like /posts/123/edit.
  • Admin logic (if any) must also be implemented in JavaScript.
  • If permissions change, both frontend and backend might need updates.

In a HATEOAS System:

  • The server responds to a request for a post with only the valid actions based on the current user.
  • If the user is the creator, edit and delete links are included.
  • If the user is an admin, moderation links like suspend or review might appear.
  • If the user lacks permissions, those actions are simply omitted.

This shifts responsibility to the server — and makes the frontend more flexible and less error-prone.

Why This Matters

  • No More Hardcoded URLs

    The client doesn’t need to construct or know endpoint URLs. The server provides them directly. This means:

    • API changes don’t require frontend changes.
    • URL structures can evolve freely.
    • Clients can be more generic.
  • No Duplication of Business Logic

    The frontend doesn’t need to understand roles, ownership, or permissions. It simply reacts to the links it’s given.

    • If no edit link is present, it doesn’t render the Edit button.
    • If a moderate link is included, the client knows the user has elevated permissions.
  • Fewer Bugs and Less Maintenance

  • In traditional apps, permission logic is often implemented in both client and server. If business rules change (e.g., adding admin moderation), you have to update both sides.
  • With HATEOAS, only the server’s behavior needs to change. The frontend naturally adapts by rendering whatever actions the server exposes.

Final Thoughts

Using HTMX and embracing HATEOAS has shifted how I think about frontend/backend responsibility. Instead of duplicating logic across layers, I now think of the server as the authority on what the client is allowed to do. The client’s job becomes simpler: render what it’s given, and follow the links.

This makes applications easier to evolve, harder to break, and more aligned with true RESTful design.

Need a fresh perspective on a tough project?

Let’s talk about how RDG can help.

Contact Us