Creating a Spaceflight News Blog with HTMX & JSON API
The other day, I was casually browsing the web and stumbled upon the need for an API for my new little project. Instead of starting from scratch, I thought it would be great if I could find an existing API to build upon. That's when I came across this repository consisting of public APIs.
As I was browsing through the list of public APIs, I couldn't help but think how cool it would be to create a tiny website using some of these APIs. It just seemed like such a fun project that could be quickly put together and shown to others.
But guess what's even more exciting? Building this website using the available APIs with HTMX instead of our typical Single-Page Application (SPA) frameworks!
Why
Well, hype aside, I find this exciting because of the challenge it presents. Itās no secret that HTMX can work with both hypermedia and JSON responses. Although, HTMX is primarily designed for hypermedia. However, I want to prove that it's completely possible (and not even that difficult) to use HTMX with JSON API as well.
JSON is the most popular data format for APIs
Also, this seems to be a common real-life scenario that many encounter.
Just imagine someone saying, "Hey, I want to migrate to HTMX but I already have a bunch of JSON APIs. Do I have to change my entire server-side implementation? What a bummer!".
So, today, Iām going to write about how I came to create a very simple website powered by HTMX, Nunjucks, and Spaceflight News API (SNAPI). But really you can replicate this with any JSON API of your choice.
Static Sites
I love static websites. They are fast, cheap, and super easy to host. The best part? They hardly require any maintenance!
I really like the idea of serving dynamic content from a static site with just a single HTML file. When you combine it with HTMX, it takes away all the hassle of dealing with messy JavaScript code in your HTML files.
Prerequisites
- Basic knowledge of HTML and JavaScript
- A code editor with a live server for testing (e.g., Visual Studio Code with the Live Server extension) or any code playground like JSFiddle
Goals
By the end of this, you will have built a Spaceflight News blog page using HTMX with the following features:
- Displaying blog posts with titles, authors, publication dates, and summaries
- Pagination with a "Load More" button
- Search functionality
The final outcome would somewhat be akin to this āClick to Loadā example, but built with an actual JSON API (refer to SNAPI documentation).
Implementation
Step 1: Basic HTML Structure
Let's get started with building our web page. The first step is to set up the basic HTML structure. It's super easy!
Just copy the provided HTML code into a new HTML file. You can name it something like index.html
. Oh, and don't forget to include the necessary script in the <head>
section:
Now, before we move on, I want to share some libraries that we'll be using:
- HTMX for AJAX interactions
- Nunjucks for client-side templates
- Optional: water.css classless CSS for basic styling
API Schema
Here, weāll be using the /v4/blogs
endpoint. According to the SNAPI docs, we've got an example response that we can work with:
If we take a look at the JSON response, it looks like we can make good use of the title
, url
, summary
, and published_at
fields to create our blog page.
The first 10 characters of an ISO 8601 date string format are in the format YYYY-MM-DD. So weāll use the first 10 characters of published_at
as our published date later.
The next
and previous
keys will come in handy for pagination.
Step 2: Client Side Templates
Next, we'll delve into actually calling the API and displaying the available blog posts on SNAPI.
Now, let me break it down a bit:
- We use the
hx-ext="client-side-templates"
attribute to activate the client-side templates extension for HTMX. This little beauty allows us to employ a templating engine (e.g. Nunjucks) to transform the JSON response from the API into HTML before it shows up on the page. - The
nunjucks-template
attribute specifies the name of the Nunjucks template (blogs-template
) we'll be using to convert the JSON response from the API into HTML. This template comprises the following elements: - A count of the total number of results
- A list of the results, each featuring a title, news site, published date, and summary
- When the
hx-get
event is triggered onload
, thehttps://api.spaceflightnewsapi.net/v4/blogs/
endpoint is called and the response is parsed as JSON. The Nunjucks template is then used to render the JSON response into HTML. The rendered HTML is then swapped into the DOM, replacing thediv
element with the IDblogs-template
.
Now, let's take a peek at all this in action on our browser...
Huh, it should have worked smoothly, right? Why is the blog section of our page completely blank?! Where are the blog posts?!?!
Debugging: CORS Workaround
Letās check this out with some good old browser inspection. Checking out the Console tab, we see an error message stating:
Ugh! It seems to be a CORS error. A bit of Googling led me to a helpful GitHub issue. After a bit of reading, I found out that there's an event listener for htmx:configRequest
that we could use.
We need to work around this issue because the Spaceflight News API doesn't allow cross-origin requests by default.
Here's the script to add to the <head>
section to implement the CORS workaround when making requests to external APIs with HTMX. It essentially just removes any custom headers:
We can now see a list of blog posts being rendered on our HTML page! Yay!
However, we are only seeing the results from the first page. Our next step is to work on the pagination part: add a "Load More" button at the bottom of the page.
Step 3: Pagination
The "Load More" button is implemented as a <button>
element:
When the āLoad Moreā button is clicked, hereās what happens:
- The
hx-get
event is triggered. Thenext
variable is used to specify the URL of the next page of blogs. The HTML that gets swapped into the DOM is the same as the one for theblogs-template
element but with some fancy new blogs added to the end. - The
hx-swap
attribute basically tells us how we should swap the new HTML into the DOM. In our case, weāre using theouterHTML
swap mode. This means that the new HTML will replace the entire existing HTML for theblogs-template
element. - Lastly, the
hx-trigger
attribute tells us which event will trigger thehx-get
event. Here, we're using the good ol'click
event. So, whenever you click on that "Load More" button,hx-get
event gets triggered and our pagination game begins!
Thatās it! Weāve now got a āLoad Moreā pagination implemented for our blog.
We're not done yet! We need to find the blog post about the Chandrayaan-3 lunar exploration mission. So, let's keep clicking that "Load More" button...and more...and more...
Step 4: Search Input
Just kidding! Who would want to keep clicking more to look for specific stuff? Thankfully, the /v4/blog
of SNAPI supports search queries out of the box. So, we can easily search for the article about the Chandrayaan-3 lunar exploration mission.
Let's work on modifying the original div
to a search input
. So, you can easily type in your search keywords and find the articles you're interested in:
So, the <input>
element acts as a search bar that uses the hx-get
event to load a list of blogs from the API when you type in a search query.
The hx-get
event is triggered by the load
, keyup
and search
events (reference). The search results are then rendered in the #result
element using the blogs-template
Nunjucks template.
Finally, I can search for āChandrayaanā related blog posts. No more endless clicking āLoad Moreā!
Conclusion
We have successfully created a Spaceflight News blog page with live search functionality, dynamic content loading, and client-side templates using HTMX and JSON API.
So, whatās next? You could give the blog page a makeover by incorporating infinite scrolling, just like this. Or you could add a next-previous button instead.
For a better search experience, you could try to update the search input to sync with the search query of the URL so that you can do something like this.
Thanks for reading!
References
Making this wouldnāt be possible without these awesome resources: