The Modern .NET Show

S06E13 - Navigating the Web of HATEOAS and HTMX: Unleashing the Power of Hypermedia and Simplified Front-End Wizardry with Sander ten Brinke


Support for this episode of The Modern .NET Show comes from the following sponsors. Please take a moment to learn more about their products and services:

Please also see the full sponsor message(s) in the episode transcription for more details of their products and services, and offers exclusive to listeners of The Modern .NET Show.

Thank you to the sponsors for supporting the show.

Embedded Player

S06E13 - Navigating the Web of HATEOAS and HTMX: Unleashing the Power of Hypermedia and Simplified Front-End Wizardry with Sander ten Brinke
The .NET Core Podcast

S06E13 - Navigating the Web of HATEOAS and HTMX: Unleashing the Power of Hypermedia and Simplified Front-End Wizardry with Sander ten Brinke

Supporting The Show

If this episode was interesting or useful to you, please consider supporting the show with one of the above options.

Episode Summary

In this groundbreaking episode of The Modern .NET Show, host Jamie Taylor sits down with Sander ter Brinke, a distinguished .NET developer and MVP, to unravel the mysteries of two transformative technologies: HATEOAS and HTMX. As the conversation unfolds, ter Brinke sheds light on how these technologies can revolutionize the landscape of web development, offering developers powerful tools to build reactive and interactive web applications.

The journey begins with a deep dive into HATEOAS (Hypermedia As The Engine Of Application State), a critical aspect of RESTful API design. Ter Brinke passionately argues that HATEOAS is not just a choice but perhaps the only true way to adopt REST for API-based services. He shares insights into how it can enhance the discoverability and usability of APIs, emphasizing the importance of hypermedia in driving application state transitions.

As the discussion evolves, the spotlight turns to HTMX, a JavaScript library that enables developers to craft reactive frontends without the bulkiness of traditional frameworks like React, Angular, or Vue. Ter Brinke nostalgically reminisces about the simplicity of Web 1.0 applications, highlighting the elegance of HTML templating engines. He masterfully connects the dots from those early days to the rise of single-page applications (SPAs) in the Web 2.0 era, revealing how HTMX rekindles the spirit of minimalistic, yet powerful, web development.

“So HTMX is, in principle, a JavaScript library, which you can use… so you can use it in your application to write a whole lot less JavaScript,” explains ter Brinke. He takes listeners on a journey back to the fundamentals, exploring the era when interactive web applications were born, and showcases how HTMX enables developers to achieve rich interactivity without the need for extensive JavaScript code.

Throughout the episode, ter Brinke’s passion for simplifying web development shines, as he articulates the benefits and practical applications of both HATEOAS and HTMX. From enhancing API discoverability to building responsive and dynamic frontends, the insights shared in this episode open doors for developers looking to navigate the evolving landscape of modern web development.

Tune in to this episode of The Modern .NET Show to gain a deeper understanding of HATEOAS and HTMX, and discover how these technologies can shape the future of your web applications. Whether you’re a seasoned developer or just starting your journey, the wisdom shared by Sander ter Brinke offers valuable insights into the art and science of crafting exceptional web experiences.

Episode Transcription

Hateos allows you to add links to the actions you can perform with the data you’re returning. So imagine a tweet and imagine, for example, just a links. It’s just an object with some arrays. And one of the links could be a retweet link or like a favourite link or like a delete link. And each link contains a type, which is like the HTTP type, it contains the URL to where you perform this action, and it also contains like a name. So kind of human readable kind of name. So like like retweet, delete, stuff like that.

- Sander ten Brinke

Welcome to The Modern .NET Show! Formerly known as The .NET Core Podcast, we are the go-to podcast for all .NET developers worldwide and I am your host Jamie “GaProgMan” Taylor.

In this episode, I spoke with Sander ten Brinke about HATEOAS and HTMX. These are two separate but complementary technologies which help to build reactive web applications. In fact, as Irina pointed out back in episode 2 of the current season (released on Sept 22nd, 2023), you’re likely not building RESTful services if you’re not doing HATEOAS.

And HTMX is something, as you’ll find out, which aims to simplify building HTML-based apps that utilise web-based APIs by taking care of the boilerplate JavaScript code that you might need to include, using a series of attributes that you can place on elements.

So HTMX is in the principle, it’s a JavaScript library, which you can use. So you can use it in your application to write a whole lot less JavaScript.

Let’s think back to the good old days, right, where we were writing, like, Web 1.0 applications and our servers were simply like, we’re using HTML templating engines, which they still do.

It worked and it worked fine, but it wasn’t very interactive because then we kind of got to the point where we were like, we want to do some cool clients application, but we don’t want to reload the page the entire time. And that is kind of where the SPA movement came along. We want to be able to have a rich interactive application where clicking a button or clicking multiple buttons, just a bit of the page refreshes, right? That’s kind of the Web 2.0, I suppose.

- Sander ten Brinke

So let’s sit back, open up a terminal, type in dotnet new podcast and we’ll dive into the core of Modern .NET.

Jamie : So Sander, welcome to the show. It’s been a while we’ve been trying to get this going and I keep having things come up, so I apologise for that. But yeah, it’s wonderful to have you on the show.

Sander : Thank you. It’s a pleasure to be.

Jamie : Awesome. Thank you very much.

So we met back at MVP Summit, the most recent one because I’m not sure when this one’s going out. So yeah, we met at MVP Summit and actually I remember right, peek behind the curtains. I remember it was during breakfast. I’d gone downstairs for breakfast. Yeah. And I had my .NET core podcast hoodie and we started a conversation with that.

Sander : I was kind of looking for other MVPs in the hotel to kind of talk to and stuff like that. And yeah, I recognised you and I recognised the show as well. So I thought it was really exciting. It was really fun.

Jamie : Yeah, see, networking, it’s like LinkedIn but for real life.

Awesome. So yeah, like I said, welcome to the show. I was wondering, would you give the listeners a bit of an elevator pitch? Like a quick description of who you are, the kind of work you do, that kind of thing, all that kind of exciting stuff so that everybody knows a little bit about you?

Sander : Sure thing. So my name is Sander ten Brinke, I am from the Netherlands and I work as a Senior Software engineer at Arcady in Zwolle, which is a consultancy company. And besides that, I’m also a Microsoft MVP. Well, which you’ve already probably understood from now.

So I’ve been an MVP since last year, which I was super, super happy to become. I mostly focus as a programmer on doing stuff with .NET and Azure and stuff like that. Those are really mainly my focus points. But I also like doing like frontend developments or I did some game development in the past, some app development, DevOps; basically everything that kind of is inteRESTing to me I love doing.

And yeah, besides all of that, I like to write some blogs on my websites, speak at meetups and conferences, doing a bits of open source or organizing some small events like Hacktoberfest, stuff like that. So I like to keep myself busy.

Jamie : Cool.

Yeah. I fully appreciate the content creation side of everything and sharing the knowledge because I’m very similar. Right. I don’t get to talk at conferences so much these days, but I love putting out content for people to sort of learn and grow from. That’s why I do the podcast, right? Is that why you do it? Or are you just like, "free time sucks. I’m just going to write all the blog posts!"

Sander : I still haven’t really, can’t really easily explain why I do it so much. I just in general, like sharing knowledge. I remember a few years ago my boss asked if I would like to speak at a conference and stuff like that at some point in my career and I said, "if there’s one thing that I never ever want to do, it’s to speak at a conference." And now I doing it, I don’t know, multiple times per year. So something really changed there. I think for me it just really developed organically where I sharing knowledge with colleagues and stuff like that. And I really like learning every day, so why not share it within colleagues? And then I just kind of got challenged slowly to share it in a presentation and stuff like that. And then it’s like, why not write a blog post?

And at some point when you’re sharing it online and stuff like that, you get all of that feedback that just makes you want to write more and more. You just start appreciating it more.

Jamie : Totally. No, I fully appreciate what you’re saying, the. I fully agree with you.

There’s something from my teacher training days which is sitting at the back of my brain and saying, "hey, mention this."

So long time listeners of the show will know that I trained to be a high school teacher just out of uni before I started my dev career. And one of the great things about giving a talk or writing a blog post or producing any kind of content is that in order for you to fully understand the thing that you’re trying to teach teaching, it helps you to let me try that again. Yeah, no, we’ll keep that in, we’ll keep that flub in. That’s fine.

In order to teach something, you really need to know it. But the act of teaching, it helps you to reinforce the knowledge you already have. Which is one of the reasons why I always used to get in my lessons. I would get the students up at the end and say, "tell me what you learned. Right. Do a mini presentation about what you learned today." Because it would reinforce that the day’s learning way better than homework ever does.

And everybody hates homework anyway.

Sander : And you get a little bit of interaction and stuff as well.

Jamie : Yeah, absolutely. Cool.

So one of the things that I would love to talk to you about is this HATEOAS, which sounds like a Linux distribution, right? But it’s something to do with APIs. I know REST, I know SOAP, I know WCF, all those kinds of things. But HATEOAS; what’s this?

Sander : So HATEOAS is definitely not a Linux distro though. Like lots of people I tell about, I talk about HATEOAS think that it is because it kind of ends with OS and stuff like that or AS. So HATEOAS is kind of it stands for Hypermedia As The Engine of Application State, which is an acronym you’re not going to remember.

And what it basically does is it enriches your API response and it can be extremely, extremely useful. That’s kind of really in a nutshell.

Jamie : Cool. Okay, so let’s say I want to use HATEOAS as part of an API. What am I doing here, right? Because my APIs will usually return a JSON Blob with some data in it. Am I still returning that JSON? Am I still using RESTful, Get and Put and Post? How do I implement that exactly?

Sander : That’s exactly kind of the I like explaining it as follows. I always use like Twitter, or I guess I should call it X now as an example.

So imagine we’re looking at just a basic Twitter application and we would be returning a tweet, right? So as JSON, we would be returning stuff like an Id, UserId, and a tweet, the amount of favourites, the amount of likes, right? That’s just the model. Just some data JSON that we’re sending over the line.

So with that data, your app is going to render some stuff on the screen. But the app only knows your data as data. It doesn’t know what to do with it. HATEOAS allows you to add links to the actions you can perform with the data you’re returning. So imagine a tweet and imagine, for example, just a links. It’s just an object with some arrays. And one of the links could be a retweet link or like a favourite link or like a delete link. And each link contains a type, which is like the Http type, it contains the URL to where you perform this action. And it also contains like a name. So kind of human readable kind of name. So like like retweet, delete, stuff like that.

Jamie : Okay, so I’m imagining that I can return, like you said, right, I’m returning the data and some things I can do to that data, right? So presumably it makes my UI easier to build, because if I’m saying, "here’s the data and here’s what you can do with it," then I don’t need no logic in my yeah, that’s that’s.

Sander : Kind of exactly it. Like, if I had to give, like, a real elevator pitch about the usefulness of yeah, that would definitely be the definition of it.

Because imagine, you’re building, like, a frontend application and basically all of these frontend applications are built like this nowadays, where you’re returning data from your API, like a Tweet. And then somewhere in your frontend, you’re building the actions based on that entity. So for a tweet could be a retweet. So there might be some logic connected to it, like you’re only allowed to retweet it if you haven’t retweeted it yet or something like that, if that would be valid logic. Or maybe downloading and deleting an invoice when it hasn’t been approved yet, something like that. There’s logic attached to actions.

Jamie : Sure, okay.

Sander : Yeah, I think that would be a good way to say it. And you might think, "yeah, that’s just something that every application has to do." But then you come to realize that the server is performing these exact same actions. When I’m, for example, deleting a tweet and there’s some logic connected to it: the owner is only allowed to delete a Tweet. You check that in the frontend to show a delete button, and then when you’re performing the delete action on the server, you’re performing the exact same action again, which is duplicate code.

Jamie : Okay. I can also imagine perhaps that because it potentially reduces the amount of code on the frontend, it likely reduces the attack surface.

So like if in your example, I can delete this thing if I’m the owner of this thing, what’s stopping me from hitting F12, hitting the breakpoint on the "do you own this thing? Yes. Allow it to delete." Right. Whereas I guess with HATEOS, if the UI is being built based on that response, that button is only going to be there if the server tells me I could put that button there, right?

Sander : Yeah, I guess it could be a bit better. I mean, you could still forge a network request anyway if you know what the Uri would be. So I don’t really think it matters security-wise. I think the biggest benefit really is the removal of lots of logic from your frontend. What you already mentioned, because your frontend no longer has to have the duplicate code, your frontend can simply check like, "is there a delete link available in the links array? If so, I don’t even care what the logic looks like, I can just now render the delete button."

Jamie : Okay. And with that reduction of duplicated logic everybody talks about don’t repeat yourself. With the reduction of that duplicated logic, if it changes on the backend, where the rule is now, you can delete it. If you’re the owner and it’s Tuesday and you recently drunk a coffee, you would then need to replicate that on the frontend. Right.

Sander : That’s exactly the problem. Yeah, that’s exactly the problem that all of the applications nowadays have. You’re changing any kind of logic on your server related to entity actions, which is like if you just think of any application, there’s loads of these, like, webshop of your cart interacting with your cart, like a time-sheet or like our registration application, all of that kind of stuff. There’s so many actions and you’re changing your backend, meaning that you also have to change your frontend. So your UI works with the new logic. And if you were to use HATEOS or just use links, so your API is sending back links to these actions, your frontend would be updated automatically.

Jamie : Right. Okay. So like you’re saying it makes my UI reactive without really having to do anything. As long as the bit of logic is there that says "if there is this link show this button," it will automatically react because then I change something on the server. Bang, my UI changes. I suppose.

Sander : That’s exactly right, yeah. So that maybe it might not even sound that impactful that, "wow, that’s such a different way to think about things." But I really, really like this approach because if you’re thinking of Twitter, again, Twitter has tons of apps available, right? They have a web app, they have like a Windows app, iOS, Android and all that kind of stuff. Meaning that they would have to update kind of the same logic in multiple programming languages, multiple tests, test runs, multiple release runs. It would save just so much time and money and so much effort if you can just update your backend and magically all of your apps are updated.

Jamie : I suppose it simplifies things like environments as well, right? So if you’ve got a dev environment, you don’t want to somehow make your dev version of the UI released to Prod without changing. Because in the REST way, I wonder if REST is the opposite of HATEOS. But we’ll just call it that for now for simplicity.

In the sort of traditional web API way, if my frontend is going to post out to somewhere, it needs to know where to post out to. So my dev build will likely be posting out to a dev server, whereas my Prod build, I want it to post out to a Prod server. But if I somehow manage to deploy my dev code to the Prod server without changing those URLs in the UI code, then I’m going to have a bad time. But I suppose if the server is telling me the UI where to Post to, or where to Get to, or where to Delete to, then I don’t need to worry about that. Right?

Sander : That’s exactly right. Yeah. That is definitely a way to kind of decouple your frontend and your backend a bit further.

Now, that is kind of the theoretical benefit of it, if I’m honest. Someone, if a listener here has been thinking, oh, that sounds really useful, they might also have a question about a situation where HATEOS might fall a little bit flat. And that, for example, could be the situation where, "well, what does my request body look like?" Right? Because HATEOAS doesn’t specify that by default, you can do that. But what I like to do is see HATEOAS as a solution to the problem of duplicate code in your backend and frontend. And I would still like to use a generated API client and specify a URL somewhere, because that is not really a big problem for me. The problem is duplicate code. The problem is not for me. That the fact that I need to specify a URL to the backend, if you know what I mean.

Jamie : Sure, okay. I was just sort of thinking of other ways that it could help.

Sander : Yeah, no, definitely. It’s definitely useful like that.

Jamie : Okay.

Sander : I’m just thinking. So one thing that I found inteRESTing, what you just said is you said that, "HATEOS might kind of be the opposite of a REST API."

The fun thing is that in order to have a fully compliant REST API, you need to implement HATEOS, which is something that a lot of people do not actually know. A lot of people say, "oh, I’m building a REST API." And then I say, "okay, so how are you using hypermedia in your API? How are you linking to other actions"? And they’re like, "well, I’m not." And then if you look at the idea of what a REST API is, which was written by Roy Fielding, the inventor of the REST principle, that is not a compliant REST API.

Jamie : Right. Okay, so you’re telling me that I’m not RESTful?

Sander : Yeah. You’re not RESTful. You’re REST-like. Exactly.

Because the entire kind of idea behind REST as well is that there’s a lot more order in your applications. And with the idea of REST is that you and the idea of the World Wide Web is that we’re using hypermedia. And that’s also kind of what HATEOS intention is. It’s hypermedia as the engine of application state.

So instead of having the frontend kind of be the engine of state, like the frontend knows what the state is, the frontend modifies it. Instead of that, we’re now using kind of the server, we’re returning the hypermedia, these links, and those are now kind of the thing that drive our application to evolve our models further, if that makes any sense.

Do you have a WPF application and want to take it to macOS or Linux? Avalonia XPF, a binary-compatible cross-platform fork of WPF, enables WPF apps to run on new platforms with minimal effort and maximum compatibility.

With a few tweaks to your project file, your WPF app and all its dependencies are ready for testing on new platforms.

Start your app transformation journey with a 30-day free trial.

Head over to to get started today.

Jamie : Sure, that makes sense. Right. Because like you say, you’re duplicating the code, you are moving the engine that supplies the links and kind of the logic to the UI, you’re controlling it from that hypermedia. So then it makes your, I guess your… "thin clients?" Is that what it becomes? Right, because I need to throw some HTML together with some maybe the bare bones JavaScript. I maybe don’t even need a frontend, like a SPA frontend or anything like that.

But then you did say something earlier on where you said, "I can generate a client." Is that something that HATEOS lets you do? Because obviously it’s supplying, "here’s the data and here’s some actions for you to perform then." Yeah. Is that like, what? I could just push a button and just generate my frontend? Is that right?

Sander : Technically, yes. That’s also a good bridge to the next kind of topic about this.

So the thing that I meant with API client, with the client generation is more like the fact that I still use OpenAPI, use swagger to generate an API client for me, including the request bodies and stuff like that. So there is a bit of coupling to the frontend and backend just because it makes my developer life a lot easier.

But you’re touching upon the fact that, "well, if you’re now returning data and we’re also returning possible actions to the client, what use do I have for a custom application? Can’t I just generate an application based on all of that information," right? That’s your point.

Jamie : Yeah, totally.

Sander : That is possible. It never really took off in the sense of when we were turning JSON and then create an application based on it. It is definitely possible. And this goes a bit deep into the entire hypermedia movement: you also need to kind of make like, a hypermedia client that understands all of this stuff and then renders it. The big problem that you can probably imagine with this is that if we’re returning links and the client has to render them, it’s not very difficult, but your application will look very, very static, very boring. Right? Because you just need to define somewhere where to put those links. It probably works like in a Web 1.0 scenario, but if you need any kind of customization interaction in your client, then this all falls apart.

Jamie : Okay, so we’re still going to need something that is inherently interactive, but it reduces that burden of where to go to get the data or what I can do with that data. Am I still in the right ball park?

Sander : Definitely. If we’re thinking, I would love to talk a bit about HTMX later, which is going to definitely touch upon more of creating a thin client and using hypermedia and kind of HATEOAS is then embedded in that as the driver for your application going kind of back to the roots. But I think it could be good to touch upon that later.

But, yeah, if we’re just using JSON and returning the links as HATEOAS kind of in your response, you definitely need to have the application understand these links and have some logic in your code that kind of still displays the buttons somewhere.

Jamie : Okay, so what am I looking for? It’s not a reason to fire all the frontend devs. You still need the frontend devs, right?

Sander : Yeah. No, you definitely still need the frontend devs, but you will make the lives of frontend devs a whole lot easier. In fact, I’ve been using this HATEOAS principle in lots and lots of applications, and it has made it a lot easier.

Because instead of having to have all of this logic about, oh, can we, for example, like you said, "is it Tuesday? Am I drinking a coffee? And am I the owner of a Tweet? And then I can delete it." All of that logic. Just let the frontend devs check a link and let them do what they do best. Right? Like make beautiful frontends. Like, use the CSS Wizardry, which I don’t understand, to just make that beautiful application, but don’t make them rewrite all of the backend logic in like, TypeScript or JavaScript or stuff like that.

Jamie : Sure, I totally get what you mean about CSS Wizardry. I literally had to center a div today and had to look it up, because I can’t do it man.

Sander : I have the same problem. I can do Angular, I can do React, I can do Vue. But the second I need to do anything with CSS, I just all fall apart. It also makes it difficult for me to think and say, "am I a full stack engineer if I do not really understand CSS?" Because I can do frontend. But the second someone says, yeah, "can you move that button?" Then? No, not really. But I can set up the cloud services for you. I can set up a bit of networking, I can do DevOps, I can do backend. But yeah, CSS. No, not for me, thanks.

Jamie : I suppose it’s like, I don’t know whether you get this, but I get this a lot for when family members say to me, "hey, you’re good with computers. Can you set up my phone?" It’s like, to me, that’s the full stack dev who’s like, "I can’t do CSS, but I can do everything else." That’s the same thing. I can technically do it, I just don’t want to.

Sander : Yeah, I’m not really specialized in it. I could learn CSS. It’s just such a different way of thinking.

Yeah, I remember being at a birthday party where a family member stayed just a little bit longer just to wait for me to arrive because he wanted to have laptop advice, and I gave it and then he left. I’m like, "okay, great." I was really thinking of sending an invoice.

Jamie : That’s brilliant. I’ll stay around just long enough to get my advice and then I’ll leave. Brilliant.

Sander : Exactly. Good to see you, too.

Jamie : So you mentioned earlier on HTMX, right?

Sander : Right.

Jamie : Because you said it was related to HATEOAS, so let’s talk about that. Right, I’m cheating. Right. Listeners, you already know that when we do this, I do a little bit of research, so I know what HTMX is. But some of you who are listening may not know what HTMX is. So what’s HTMX then?

Sander : Well, I feel like you say that your listeners might not know it, but one of the things that HTMX is currently, it is extremely popular on social media, especially on Twitter, which is kind of why it has been exploding and exploding. So if people are, like, listening to tech podcasts, they might have at least seen a lot of the memes already. It kind of got popular because of the memes, which I find a very interesting marketing strategy for your library.

So HTMX is in the principle, it’s a JavaScript library, which you can use so you can use it in your application to write a whole lot less JavaScript. Let’s think back to the good old days, right, where we were writing, like, Web 1.0 applications and our servers were simply like, we’re using HTML templating engines, which they still do. But nowadays, lots of applications are like single page applications, and the server was returning HTML. And then the only way we could interact with servers was with the anchor element and with forms. Right. So we could do like Gets and Posts, which worked very, very well. We clicked on a link or we submitted a form and then we had to go to the server and then we got some HTML back.

It worked and it worked fine, but it wasn’t very interactive because then we kind of got to the point where we were like, we want to do some cool clients application, but we don’t want to reload the page the entire time. And that is kind of where the SPA movement came along. We want to be able to have a rich interactive application where clicking a button or clicking multiple buttons, just a bit of the page refreshes, right? That’s kind of the Web 2.0, I suppose.

And that’s where it all went wrong. No.

So the idea is that we’re now bootstrapping like an Angular -I guess React is the most popular application - and for example to click on a button and then we do like lots of react magic and just to send kind of an API request to get some data or to perform some actions on the server. HTMX, to get back to that, is simply in the basic form, the fact that you can perform HTTP requests on any element. So you can for example, perform like an HTTP Put request, you can perform Gets, and Puts, and Posts, and Patches, and ,Deletes and all that kind of stuff from any element, from lots of interactions on a div, on like an h1, on buttons, on p elements, stuff like that.

Jamie : Okay? So it allows me to add that interactivity to all of my elements using new attributes. So I can have like, I don’t know, pulling something out of the air like a delete button, right? I can make a delete button do a delete thing. Right? Or rather I can make a button do a delete thing exactly. By adding something right there’s. Some magic happens, I can just go, "splat, this becomes delete," and maybe it knows to post to the delete URL.

Sander : Is that what’s happening? So what we could for example do is, well, let’s just say we’re using a button without a form. So the button could have, I don’t even know the bracket, just like the button element in HTML. And you could, for example, say, hx-delete. And then you could put the URL in there, and then what it would do is it would perform like a JavaScript request to that URL, and your server could then return HTML and it would swap the changed… it would return HTML. Sorry, your server would return HTML. And it would render the HTML on the page. And this is kind of a very rich interactive thing to do. We’re not like clicking a button and reloading a page, losing all of our state. No, we can still keep state in the frontend and keep create rich applications. But now performing, for example, a search in your HTML was simply using one little attribute instead of having to write like 50 lines of JavaScript.

Jamie : Okay, so we’ll go back to our Tweet example. We’ve loaded the tweet. I want to delete the tweet. I’ve done something in my frontend code to add this hx-delete attribute, with the delete URL. I hit the button, it deletes it, we get a success from the server, or we get something from the server. And then, maybe I’m returning some HTML from the server, like you say. Then the HTML for the tweet and the delete button are then re—I don’t want to say "rerendered", but it’s replaced with whatever came back from the server.

Sander : Exactly. You could, for example, have a div somewhere, like under the delete button, which has an id like delete-result. And then you could, for example, say in your delete button, you could say hx-swap and then delete-result. And then HTMX would automatically perform that action. When it’s done, it would grab the HTML from the server that’s returned and it would put that HTML in that div.

It sounds very, very simple, but if you’re thinking like how this currently works, you’re writing literally like one line of code that does a whole lot of interactions for you that you would currently do with JavaScript.

Jamie : Right, okay. Because I know we’re going to come back to HATEOAS in a moment, right. Putting that to one side at the moment, let’s say I’m just returning JSON Blobs or whatever from the server or whatever. If I’m just using HTMX, I still need something that when it prepares that page template, it knows to put the URLs in. So maybe it’s being rendered on the server, maybe I pull some data and then it renders it in the UI. But I guess because we mentioned HATEOS earlier on, this is where the two join together and become a superpower, right?

Sander : Kind of. That’s the tricky part.

So the concept of, like, hey, to us returning links and stuff like that is kind of the idea of hypermedia. And hypermedia what that is returning media, like text from a server, but it’s interactive, you can link to stuff. That’s the entire idea of hypermedia. I know this is kind of going on on the tangent, but you need to understand the big picture to understand kind of the relationship or the non-existing relationship between HATEOSS and HTMX.

So the World Wide Web is basically media which is connected to each other, right? Like I can go to Google, then I can click on a link to go to Wikipedia, and then from Wikipedia I can go to like Twitter or something and it’s all connected, right. And what is happening is that your browser is getting all of this hypermedia back and it already understands what it needs to do. Your browser is like a. Hypermedia client. It sees an anchor link, so it knows that when someone clicks on that link, it needs to connect to a new application, which is, for example, Twitter.

So now let’s go back to a traditional, just like nowadays, SPA application. We are returning a tweet which has a userId, but that isn’t real hypermedia because the client doesn’t understand what—the client doesn’t natively understand what that means, your browser doesn’t understand it. It needs, for example, React to then render that to HTML, and render that userId to a link to open the user ID to user page.

Okay, do you understand the difference?

Sander : Do you see the difference that I mean?

Jamie : Yeah, I’m struggling to think of an analogy. Usually I’m pretty good with metaphors and analogies, but I’m struggling to think of one. But no, I get what you mean. I feel like HATEOAS takes us back a step to a simpler time where we are just transferring hypermedia around because SPAs are complicated, right?

Sander : Yeah. Let’s think of a banking application. Let’s say that we are loading our bank’s application. Our bank applications are still typically pretty old fashioned. And for example, this one’s still just returning HTML. So you can imagine that it’s returning an HTML document which has like a header with bank details, and it has a couple of bit of information like my name, and my balance. And it has three actions. It has an action to close account, and it has an action to send money to another account. Right. Imagine that in an HTML sense that would probably involve some forms and some buttons and some stuff like that that is already HATEOS. The server is returning data with links, with actions that can be performed. And the browser natively understands this as, "hey, there’s a form with a close account button," which basically is a HATEOS link. It’s a link to another action.

Jamie : Okay, so they are separate things. But where does HTMX come in then? Because if I’m going to build the greatest application ever, right, I’m going to have a .NET backend that returns HATEOS, and I’m going to magically get HTMX running at the frontend and then I’m going to make the memes about it. How am I pairing those three things up?

Sander : I think in the classical sense, in the way that I use HATEOAS is that if I’m using HATEOS in my applications, I’m not really using HTMX in the frontend. I’m using for example, like Angular or React or stuff like that. And I’m using those JSON HATEOAS links to render my actions on the client. Based on those links, when I’m using HTMX, my server is returning HTML. So we’ve stepped away from returning JSON. We can still have an API that returns JSON, but for our frontend, we’re returning HTML again. And the HTML is hypermedia that already has HATEOS a principle applied to it. We’re returning our banking details with these actions that you can perform on your account.

Now, what HTMX allows you to do is instead of clicking on that button, reloading the page and stuff like that, we’re allowing our browser to say, "if someone clicks on that button, perform like a request to the server, and return the HTML, and render it without reloading the page." Right. Like the old, good old days of using AJAX request, XML, HTTP request and stuff like that.

A Request To You All

If you're enjoying this show, would you mind sharing it with a colleague? Check your podcatcher for a link to show notes, which has an embedded player within it and a transcription and all that stuff, and share that link with them. I'd really appreciate it if you could indeed share the show.

But if you'd like other ways to support it, you could:

I would love it if you would share the show with a friend or colleague or leave a rating or review. The other options are completely up to you, and are not required at all to continue enjoying the show.

Anyway, let's get back to it.

Jamie : Right, okay. So like you said earlier on, I guess both HATEOS and HTMX are greatly reducing the complexity of

Sander : Oh yes.

The frontend. Right. Because if HTMX is— sorry, if HATEOS is what the browser already understands and HTMX is, and I’m going to use my own words here, this is not what you’ve said, "supplying me some magic to wire up a delete button to a delete action." Right. Then my user interface becomes less complex. So then it becomes faster to innovate with, I guess.

Sander : Oh, yes, definitely.

So to kind of hammer that example home, right? Let’s just kind of see if we can explain a search action to the listeners. It’s always really easy to explain it with code, like on the screen, but of course some people might be in a car now. So let’s see if we can explain this with our voices.

Jamie : Good luck, everyone.

Sander : Pay attention, but also pay attention to whatever you’re doing.

We’re writing a search function in our application. So we’re searching, for example, a recipe application for the most nice dinner recipes that you can imagine. And we’re doing this in a React, or Vue, or Angular - a modern SPA application - that involves quite a bit of JavaScript. Right. We need to have something that listens, some input box where there’s input coming in. We need to then send an HTTP request somewhere. We need to track the state so we can, for example, put a loading indicator on or off when the request is done or the request fails. We need to handle request successes and request failures. When the request comes back and we get a response, we need to grab that JSON and we need to map that to the results. And then we need to put that somewhere so the response is rerendered on the screen.

Sounds like a whole lot of stuff I just said, right, for a pretty simple feature.

Jamie : Yeah, that’s a ton of stuff. And that’s before you start thinking about, "well, what about if my API contract changes and the model changes," right.

Sander : Exactly, exactly.

So now with HTMX and the entire, like the power of hypermedia, what we’re doing is we have, for example, an input, we have an input element and then we can say hx-get, and then we put in the URL so where the search action would be. So like "/search". And then we would also say hx-delay=“500” milliseconds. So after someone stops typing for 500 milliseconds, grab the text from the inputs and send it to that URL. And then we could still grab like the hx-swap and it said replace the swap, the HTML that’s returned, replace that in the results, the search results.

So that’s basically three attributes to replace all of that stuff that I just rambled on about. And we can just replace all of that logic with three little bits of HTML.

Jamie : Right, okay.

And I mean, it makes sense that you can do that, right? Because it’s going to be the same code every single time, right? If we were doing it in a SPA or a JavaScript application context, we would have code that performs a Get, code that parses a response, code that parses whether it was a success or failure, code that does some branching thing. We don’t need to do any of that any more because we just literally let HTMX deal with it for us, right, exactly.

Sander : And we’re just using the power of our server, which already has all of the data, it knows what the search results are and that is just returning a bit of HTML instead of JSON and it’s being rendered on the client again. So it’s the good old days of building pretty simple applications but still having very customizable frontends. So it’s a really good handshake between the good old backend developers saying, "it was so much better back in my days," and the frontend developers saying, "but I want to build rich applications."

HTMX is like a really good solution for this and it’s gaining a lot of traction.

Jamie : So does that mean then that because my backend server needs to return some HTML, does the server then need to know about what the UI looks like? Like what the UI is doing? I mean, it would anyway because it’s still returning the HTML for the original page. But before I can, as a server side, a backend engineer, I then need to get the data from the database. So I’m going to take the Get request, I’m going to get all of the things I need from the Get request to then go into the database, perhaps get the data from the database. It comes back as a list of things. I then need to iterate through that list of things and generate an HTML string or just a string that is some HTML and send that back over the wire, right?

Sander : Yeah, no, that’s exactly right. So what you can do with HTMX or I think it’s really simple, it’s again, just like one or two attributes is that you’re just sending form data like we’re used to do in the good old days. Just kind of keep saying that because it sounds nice. So it is all kind of already handled by the browser because the browser knows how to do this stuff. The browser knew that since the browser was invented, how to send stuff to the server, and HTMX is just kind of extending the entire model of HTML. Like, "why does HTML only support, like, Get and Post? Why can’t it be more interactive?" Because that was the problem, and that is why spas were invented. And now you can just do so much more while you’re just depending on the browser itself when you’re depending on HTML.

Jamie : Okay, so my server still needs to from a backend perspective, all I’m doing is I’m swapping returning JSON for returning HTML.

Sander : That’s it exactly. Magic happens, and then the magic just happens.

You can look at this in a lot of different ways. A lot of people, when they learn about this concept, is the first, and maybe that’s also a question that you have in your head. So I’m curious if you’ve thought about this yet, is, "well, what if I want to build a mobile app, right?"

So if you go to the website, you don’t have to do this now, but for a listener that might be interested in this concept. So the website from HTML, which is, I believe what you can do - and this is based on the information from those essays - is you can have two different kinds of APIs. Now. You can have, for example, a data API which is returning like JSON or HTML, stuff like that. You can have some multiple APIs depending on the client. And you can also just have like a one application API, which has all of the actions. So, like the Tweet retweeting, the deleting and stuff like that, that might also maybe still be JSON and stuff like that, but that way you could, for example, still have one backend that can serve multiple clients, if that makes any sense.

Jamie : Yeah.

So I’m imagining you mentioned it earlier on, let’s say we’ve got a Twitter app or an X app or whatever. Maybe we don’t have an X app because the iOS store requires app names to be more than one letter. So we’ve got a Twitter app, right?

Sander : Yeah.

Jamie : And we’ve got a Twitter desktop app, we’ve got a Twitter iOS app, a Twitter Android app. Like you said earlier on, they’re all communicating with that one same API, but maybe there’s an endpoint that’s returning preformatted HTML, and maybe there’s another endpoint that’s returning just the links for, like you said, those buttons, right? So I push the button for compose a Tweet, I type out, "HTMX is awesome 🙂🙂🙂," and I hit Tweet. The link for the Tweet button has come from the API that just sends me the link I’m allowed to use. Right?

Sander : Perfect Yeah. So your API for your app that might not be using HTMX could still be using JSON, and like this concept of HATEOAS where we’re returning links, so even the iOS app can still be a thin client, where then your browser application could, for example, be using HTMX with HTML to make that an even thinner client.

Jamie : Okay, that’s pretty cool.

So then how do I go about doing this in a .NET context, right? Do I need to import any kind of specific libraries in a .NET app to get the HATEOS concept? I know you’re saying, "it’s a concept, it’s the good old days." But maybe I’m a lazy developer. I just want to go nuget install someGreatNuGet that will do all for me. And if I’m doing HTMX, I can’t imagine I’d need to do anything special with my .NET APIs, right? I’m just returning HTML. I’m taking a thing and returning HTML, right?

Sander : Yeah.

So let’s talk about that HATEOS thing first because like I said, I think it’s kind of two different approaches to building applications. So for HATEOAS it’s a standard, and for .NET applications, there are lots of packages available. First, I’m going to have to plug myself a little bit here. So it’s currently Hacktoberfest [2023] and I’ve been working during Hacktoberfest on like a HATEOS library, which you can find at well, would you want me to do a link here or are you going to put it in show notes?

Jamie : Oh, all of the links that you mentioned, I’ll put in the show notes. I need to refer to it somehow. But yeah, it’s on GitHub, I guess.

Sander : Yeah. So it’s on GitHub at If you just Google my name and then kind of HATEOAS stuff, you’ll find it. But there’s also other libraries like riskfirst.hateoas. And what these libraries allow you to do in a modern .NET application is to just use HATEOAS very, very simply. So it’s like almost no work to add this kind of stuff to your application. And any frontend that you’ll have occurredly built will be very, very thankful for doing that. Super, super simple.

Jamie : Right? Okay. Just before you move on, I guess if I’m writing a web application that is grabbing some JSON from somewhere and suddenly the API swaps to doing HATEOS, let’s say they’re just returning A JSON Blob with some links. I don’t have to change anything, I just ignore the links. Right?

Sander : Exactly. It’s backwards compatible. And that is also just a little thing that I want to touch upon: so we talked about maintaining your Twitter application.

But what if you have third party applications like Twitter also does? Like you have Owly and Talon and stuff like that. Those are third party applications. Any changes you make to logic of your backend could break those applications because you can’t update those, right? Those frontends you cannot update. So the power of HATEOAS could be that you could return a delete link and then all of these third party applications, if they want, can use that delete link to determine if deletion is allowed. So you can change your server and say, "only on Fridays you can delete tweets," and even the third party applications will be updated, which is just like kind of when I kind of realized that it was kind of mind blowing to me.

Okay, so to continue right, so we talked a little bit about HATEOS and .NET. So HTMX is a JavaScript library, meaning that it works in PHP, it works with Java, but of course it works best with .NET - as we all know. No, but of course.

So there are lots and lots of really good examples and libraries available. So you have on GitHub you can find a project called HTMX.NET, which is kind of a library that makes it a lot easier to work with Razor, like Razor Pages and ASP .NET Core MVC, and kind of attach some HTMX stuff to it. And if you look at that library, you will also find an amazing little workshop that the creator of that has created that teaches you the concepts of HTMX and how to use it within .NET. Like it takes an hour or two of your time and your thinking patterns of building applications will just completely change. It was really, really mind blowing to me, so I would definitely recommend that.

Jamie : Right, okay. So you’re lighting up parts of my brain that are like, "hey, HTMX seems very JAMstacky, but without the JAM. Without the J for the JAM." Right. It’s then just APIs and markup, right? It’s an AMstack. Is that a thing?

Sander : Probably not exactly.

If it hasn’t clicked for a listener yet, you need to kind of start thinking back like exactly what you say. "Why are we building all of these SPAs? Why are we doing so much complex work on the frontend to build a little todo application?" Well, it’s just because of the interactivity that we want, and HTMX allows you to do that.

Now, HTMX might not work for all of the applications; the same goes for HATEOS. If the application is super interactive and has tons of real time updates, it might still be better to use with JSON and stuff like that. It depends on your model. But HTMX also allows you to integrate with your current JavaScript code base. So if anything, if HTMX does not work for like a specific part, you can still fall back to JavaScript and that is also a completely still thing, good thing to do.

Just something that I still wanted to throw out there.

Jamie : So it’s not that it is the best way, the only way to do web based applications. It’s just, "hey, get this tool in your toolbox and someday it might prove useful." Right.

Sander : Exactly that and even if it doesn’t really prove useful to you right away, it will - just like you said - it will just kind of light up different parts of your brain; which it really really has for lots and lots of people in the community, which is really fun to see.

Jamie : Yeah. And I think it’s always worth investigating technologies that fit slightly outside of your use case because then A) you see how other people are doing it; but then, B) you get a greater appreciation for other ways to solve the same problem because there is no one way to solve every problem. Right.

Sander : Exactly. No, you’re completely right.

I really like talking to people about exactly like this, like kind of looking at different tools because I talk to people and then I look at the modern frontend technologies, right. And then there’s like partial hydration and hydration and islands and all that kind of stuff. And I’m like, "what is happening? I just want to put an image on a screen." And then there is HTMX, which is just kind of like you go back to the Stone Age times and we’re just returning HTML again. And it’s just so very easy and it works, and it just works and it’s just so much easier for someone to grasp and kind of come to terms with.

Jamie : Sure. And I mean, I guess if it ain’t broke, don’t fix it, right?

Sander : Yeah.

Jamie : Cool. Okay.

Well, I mean, it’s been an amazing conversation with you, Sander. What about getting in touch with you? We talked a lot about Twitter or whatever they’re calling it these days. Are you on Twitter? Do you prefer people getting in touch on LinkedIn? Like, somebody’s listening to this and going, "I need to talk to that guy, he’s making me think about web development differently, and I want to go have a chat with him." How do they get in touch?

Sander : You can definitely reach me on Twitter. So on Twitter, @SanderTenBrinke, you can also find me on LinkedIn, on my website, stuff like that. I think those three are definitely the main best ones to get in contact with me, and that is also the ones where I’m most active. So, yeah, feel free to reach out. I’d love that.

Another thing you can do if you’re interested in this entire topic of HATEOS is read my blog post about it. So on my website, S Ten Brinke dot NL - because that’s the good English pronunciation for it - you can find my blog post about HATEOS there, and even how you integrate it with .NET in multiple different ways, and exactly what the benefits are. So I definitely recommend checking that out as well.

Jamie : Awesome. There’ll be a link to that in the show notes, so press through on your app of choice and definitely give that a read. I can definitely recommend Sander’s blog posts. I really enjoyed the configuration one you wrote. It was like "Everything you need to know about configuration in .NET." It was really good.

Sander : Thank you. I’m real sort of really happy with that one. It’s been doing quite well, so it’s definitely one of my proud blogging moments.

Jamie : Awesome.

Well, thank you very much for being with us this evening, Sander. I really, really appreciated it. I’m now going to go away and I’m going to rethink how this… okay, so real quick, I’ve got this app that I’ve written. It’s an API and a UI. Right. And it is just literally a search. It’s, "show me a list of books from this very small subset of books and allow me to search through it." That’s an HTMX app right there, right?

Sander : Yeah, that’s like three attributes. Yeah, exactly.

Jamie : Yeah. Okay, so I’m going to go and do that this evening, and sounds fun, man.

Sander : You should do it.

Jamie : Awesome. Well, like I said, thank you ever so much for being on the show. I really appreciate it.

Sander : Thank you. Thank you. It was really, really fun to be here.

Wrapping Up

Thank you for listening to this episode of The Modern .NET Show with me, Jamie Taylor. I’d like to thank this episode’s guest, Sander ter Brinke, for graciously sharing his time, expertise, and knowledge.

Be sure to check out the show notes for a bunch of links to some of the stuff that we covered, and full transcription of the interview. The show notes, as always, can be found at the podcast's website, and there will be a link directly to them in your podcatcher.

And don’t forget to spread the word, leave a rating or review on your podcatcher of choice - head over to for ways to do that - reach out via out contact page, or join out discord server at - all of which are linked in the show notes.

But above all, I hope you have a fantastic REST of your day, and I hope that I’ll see you again, next time for more .NET goodness.

I will see you again real soon. See you later folks.

Follow the show

You can find the show on any of these places