Devlog 15
You're viewing a Gemini article on the web
It's much better to view it on Gemini!
It's been a long time, and a lot has happened. I do actually have some news on this front, though. After all this time. Let's get into it.
Where have you been?
I've been working. I got a job writing JavaScript for a local company, which is quite nice. I will forever... not be a fan of JavaScript. At least I'm using Astro, not React. That's a lot nicer. I do actually get to come up with fun solutions to problems using as little JS as possible.
Recent work
It has been a long time since I touched this code base. Since my last post I reimplemented everything in Rust, and got really annoyed with how much work was needed to get basic stuff done (not a fault with Rust, a fault with me). I decided Java and Spring is definitely the right combo for me. A lot of the really fiddly things are already fixed by associated libraries, meaning I can focus more on what I'm actually shipping.
Out of frustration I'd actually deleted my more recent Java migration branch, so I was starting from scratch. This turned out to be a blessing. My original architecture left a lot to be desired and wasn't very extensible. I've approached this one in a much more standard way with clear separation of concerns. I have:
- Auth (form-based login and sessions backed by Redis)
- Permissions (limited, but functioning)
- Key entities implemented
After seeing the term HATEOAS repeated in the Spring Starter list, I decided to look up what it actually means. Life changing. HAL in particular makes so much sense from an API perspective I'm shocked I'd never heard of it before. I decided I'm going to use this pattern universally, which gives me a really nice template for building endpoints.
I've also started reworking the frontend. Originally, I'd planned to write the whole thing in Vue, then I switched to HTMX and Thymeleaf, then to Astro. Now, I'm back to HTMX and Thymeleaf. This time, though, I've made the decision to use HTMX only for progressive enhancement. The design goal is that the entire site should function without JS, and JS should be used only to make the experience smoother. In practice, this looks like the following:
- Every interaction in the site is driven by links and forms
- Forms sent by a standard HTTP request receive a full templated page as a response
- Links with hx-boost replace the entire page
- Forms sent by HTMX replace a target element with the templated content
This adds a lot of complexity to the implementation since multiple partial templates are needed, but I do think that trying to avoid JS where possible is a good pattern. I really don't want to have to write JS if I don't have to.
The only place I can think of where JS is going to be absolutely necessary is in the kanban board itself. Even then, I think a fallback behavior should be possible, although it will be ugly. In a JS-enabled kanban:
1. The user will drag and drop elements from one column to another
2. On dropping the card, a PATCH request will be sent instructing the server to update the target list item with the new position and status
3. The server will respond with the updated columns
In a JS-disabled kanban:
1. The user will click on a card, which requests the movie details card from the server
2. The user will select the new status/position in a dropdown form
3. The user will send the form, which will send a POST to the server
4. The server will respond with the kanban page template, including the updated columns
This approach is clunky, and nowhere near as nice as the JS-enabled kanban. However, I don't want to require users to enable JS if they don't want to. A little bit of complexity is unavoidable.
What's next?
I'm currently reworking my logic for handling movies. I have decided that I do need to actually store data from TMDB in the database, even though I was originally avoiding it. Since I'm now working with Spring, handling update tasks is a lot easier. I've decided that I will store all fetched entities and refresh them at 180 days (in accordance with TMDB's TOS). I'll still cache entries aggressively, but I'll cache them from the app database rather than from the TMDB response. If someone fetches Jaws and it's not in the DB, I will first add it to the DB, then return it and cache the response. This gives me far more flexibility when it comes to representing data in a controlled way.
Tell me what you think.