Adding Likes to Hugo site


Hey 👋, inspired by Brent Roose’s blog I decided to add a like button to all my posts in this blog. It’s a static site generated by Hugo since 2018.

It’s a nice little project that involved:

Integrating with Hugo

Let me start by saying that it was a bit difficult to decide where to add this feature. Hugo allows for multiple ways: overriding sections, shortcodes, …

First I started by implementing it as a shortcode, but when I was almost done I realised that this would require me to include in all the posts the {{< whatever_shortcode >}} shortcode, which I didn’t want to.

After that I tried to override the layouts/_default/single.html but when I was almost decided I checked the theme and there were some “partials” like the footer.

Tested the partials approach, but I didn’t like the result because I wanted my like button to be right after the post content. So I went back to the layouts/_default/single.html idea.

The process was very easy:

The frontend part

The frontend code is very simple. I separated HTML, CSS and JS in three different files.

layouts/partials/likes.html

<script type="text/javascript" src="/js/likes.js"></script>
<link rel="stylesheet" type="text/css" href="/css/likes.css">
<div class="likes">
	<div class="likes__button">
		<div class="likes__emoji">👍</div>
	</div>
</div>

static/css/likes.css

.likes {
    display: flex;
    justify-content: center;
    margin: 25px 0px;
}
.likes__button {
    display: flex;
    border-radius: 5px;
    border: 2px solid #ff8181;
    height: 50px;
    align-items: center;
    justify-content: center;
    padding: 5px;
    min-width: 50px;
}
.likes__button:hover {
    background-color: #ff8181;
    cursor: pointer;
}
.likes__emoji {
    font-size: 25px;
}

static/js/likes.js

const sendLike = async () => {
  // Get current page url.
  const url = window.location.href;
  // Send like to the API.
  const result = await fetch(
    "https://api.aaron.com.es/likes?url=" + encodeURIComponent(url),
      { method: "POST" }
  );
  // Return number of likes.
  const data = await result.json();
  return data.likes;
};

// Hook the click handler when DOM is ready.
addEventListener("DOMContentLoaded", () => {
  const element = document.querySelector(".likes__button");
  if (element) {
    element.addEventListener("click", async () => {
      const likes = await sendLike();
      element.querySelector(".likes__emoji").innerHTML = `${likes} 👍`;
    }, { once: true } );
  }
});

Everything is ready in the frontend part! 🎉 What about the backend?

The likes API (backend)

I have to admit I got a little excited and overcomplicated (only slightly) the backend part. But it was for a reason, I plan on having this backend for other future projects.

The actual API is very basic. Only a couple of endpoints:

I will go in more depth regarding the implementation in an upcoming article! Stay tunned!

Result

Here you have it. Smash the like button! 👍👍👍

PS: Don’t be evil! Right now the API is missing any checks, so you can like the same post many times. I will fix that in the future.