Hi. Have you tried using HTMX with Vapor? I find the concept of HTMX quite refreshing.
If you are new to HTMX, then here is the Fireship
100 seconds video: htmx in 100 seconds and here is the official intro by htmx.org itself:
- Why should only
<a>
and<form>
be able to make HTTP requests?- Why should only
click
&submit
events trigger them?- Why should only
GET
&POST
methods be available?- Why should you only be able to replace the entire screen?
By removing these arbitrary constraints, htmx completes HTML as a hypertext.
For various reasons, I decided to try it together with Vapor as a backend. Honestly, it is the first properly sized side project I am doing in Vapor.
As I was using both, I had to write quite a number of small helpers, and now I would like to share them with the wider community to help with adopting HTMX in your Vapor projects faster.
Meet VaporHX: https://github.com/RussBaz/VaporHX
In order to speed up the adoption of HTMX, I came up with 2 core concepts:
VaporHX
easily adds HTMX capabilities to existing API endpoints by addinghx(template: String)
extension method to allContent
,HTTPStatus
andAbort
types. In case ofContent
protocol, it will inject your content into the specified template on HTMX/HTML request and serialise it to JSON otherwise.- The library automatically selects the response type (such as API, HTML or HTMX) based on the request
Accept
header value + its method. It will also automatically wrap HTMX fragments with a dynamically generatedleaf
template to return a proper HTML during a normal browser request (referred internally aspage
). Therefore, you do not need to create a separate template when you need the whole page to be returned instead of just an HTMX fragment.
Here is a basic example:
struct MyApi: Content {
let name: String
}
app.get("api") { req in
MyApi(name: "name").hx(template: "api") // Return type is 'HX<MyApi>'
}
Of course HTMX/HTML only methods are available as well:
app.get { req in
try await req.htmx.render("index")
}
I am still working on the documentation, but the library itself is already functional enough for others to try.
Please feel free to try it and let me know how it works for you. Any feedback is welcome. This is my first public swift
project, btw. Hope you will find it useful.
Thanks!
edit: Renamed the repository