{% extends 'base.html' %} {% block content %}

I built UnTube with the goal of making it easier to manage multiple YouTube playlists.

This is the second item's accordion body. It is hidden by default, until the collapse plugin adds the appropriate classes that we use to style each element. These classes control the overall appearance, as well as the showing and hiding via CSS transitions. You can modify any of this with custom CSS or overriding our default variables. It's also worth noting that just about any HTML can go within the .accordion-body, though the transition does limit overflow.

This is the third item's accordion body. It is hidden by default, until the collapse plugin adds the appropriate classes that we use to style each element. These classes control the overall appearance, as well as the showing and hiding via CSS transitions. You can modify any of this with custom CSS or overriding our default variables. It's also worth noting that just about any HTML can go within the .accordion-body, though the transition does limit overflow.

This website is primarily built using Django, Bootstrap 5 and htmx. Django helped me swiftly set up the backend and organize them into separate apps. All of the UI you see on UnTube was built purely using Bootstrap 5. I started off with some free base templates I've found online, and slowly began designing the site myself as I was getting used to seeing repetitive Bootstrap code over and over again. By the end of this project, I've grown accustomed to using the official docs and figuring out a way to implement any feature that I've cooked up in my mind.
I cannot be thankful enough for the existence of htmx. Most of the dynamic interactivity on this site was made possible due to htmx. When I began implementing core site features like moving, deleting, checking for updates etc. I found myself writing a LOT of AJAX code each and everytime, for even the simplest of interactivity. It was when I found htmx my development process sped up like crazy. Who would have thought that instead of replacing the whole page with the response, just replacing a particular target element with the HttpResponse would do wonders? Some of the major places I've used htmx on this site:
  • HTMX Triggers htmx offers various triggers upon which it sends requests. One example is the load trigger. After the dashboard finishes loading, I've set up htmx to automatically send a GET request to the backend (this only happens once upon the page load) to check for playlist updates. From the backend, the update status is sent back via a HttpResponse which htmx promptly loads into a target div I specified. That way I did not need to check for updates inside the main view that loaded the page. In a way, htmx helped me check for updates in the "background". I've used this load trigger many other places on the site, one other example is the playlist completion time info is loaded after the playlist page is loaded.
    Instead of sending requests on load, it is also possible to send htmx requests when any HTML element is clicked or revealed. I've used this click trigger on the mark playlist/video as favorite buttons and the mark videos as watched buttons. Below, I discuss about using the revealed to achieve infinite scrolling.
  • Active Search The whole search page heavily relies on htmx. On the frontend, via htmx the textfield (as well as the select and radio buttons) is hooked up to automatically send requests with the search query to the backend right after certain milliseconds of typing. In Django, I've set up a view to receive these htmx requests and send back a HttpResponse using a template loader. htmx then loads the received response into a target search results div that I've set up. Check out this search example from htmx's website.
  • Infinite Scrolling For playlists with more than 50 videos, the next 50 videos are automatically loaded onto the screen only when the user scrolls down to the bottom. htmx's hx-trigger="revealed" and hx-swap="afterend" attributes helped me achieve this functionality. When the 50th video is revealed on the screen, htmx makes a GET request to the backend to get the next 50 videos (if available) and appends the HttpResponse after the 50th video. Until htmx gets back a response from the backend, it can be set up to show the user a loading spinner!
    The main advantage of this feature was that for playlists with 100s or even 1000s of videos, it only needs to load the first 50 videos everytime and hence vastly improving the playlist page load speed.
Any questions on how I've implemented some of the features on this site? Head over to feedback and send me your questions. I will be happy to share my code and thought process to illustrate how I implemented the site's features using htmx.
{% endblock %}