Anonymous Reactions Feature
Anonymous Reactions Feature
This folder contains the source code and documentation for the custom anonymous reactions feature built for the HAKSOAT blog.
The Architecture: How It Works
To understand how this feature works, let’s start from first principles.
At its core, a reaction system needs two things: a way to display buttons to the user (the frontend), and a way to remember how many times those buttons were clicked (the backend). Because your blog is a static site generated by Jekyll, it has no database or server of its own. It is just a collection of HTML files served to the browser. Therefore, to remember state (like reaction counts), we must introduce an external backend.
We could have used a managed third-party service (like Disqus or Lyket), but those come with trade-offs: Disqus requires a login, and Lyket has strict free-tier pageview limits.
Instead, we built a serverless architecture. This means we wrote a tiny piece of backend code that only runs when someone clicks a button, and we connected it to a lightweight, lightning-fast database.
The architecture consists of three components:
- The Database (Upstash Redis): Redis is an in-memory data structure store. Think of it as a highly optimized dictionary or hash map. We use Upstash, which provides a serverless Redis database. It stores the reaction counts for each blog post.
- The API (Vercel Serverless Functions): Vercel hosts our backend code. When a user clicks a reaction, the browser sends an HTTP request to Vercel. Vercel spins up a tiny Node.js function, which talks to Upstash Redis to increment the count, and then returns the new count to the browser.
- The Frontend (Jekyll Widget): This is the HTML, CSS, and JavaScript embedded in your blog posts. It displays the buttons, handles the click events, and uses the browser’s
localStorageto remember if a user has already reacted (preventing multiple votes from the same browser session).
Why this approach?
- Anonymous: No GitHub or Google login required.
- Free: Both Vercel and Upstash have generous free tiers that easily accommodate personal blog traffic.
- Data Ownership: You own the database and the code.
The Technology Stack
1. Upstash Redis (The Database)
- What it is: A serverless Redis database.
- Where it lives: Hosted at console.upstash.com. The database is named
haksoat-reactionsand is located in the London region. - How data is stored: Data is stored as Redis Hashes. The key is
reactions:<slug>(e.g.,reactions:lessons-from-my-father/). The fields are the reaction types (like,love,insightful,curious), and the values are the integer counts.
2. Vercel (The API Hosting)
- What it is: A cloud platform for static sites and serverless functions.
- Where it lives: Hosted at vercel.com. The project is named
haksoat-reactions-api. - Environment Variables (Security): The Vercel project is configured with two secret environment variables:
UPSTASH_REDIS_REST_URLandUPSTASH_REDIS_REST_TOKEN. These are the API keys that allow the Vercel function to securely talk to your Upstash database. Because they are stored as environment variables in Vercel, they are never exposed to the public internet or committed to this GitHub repository. - The Code: The API logic is written in Node.js and lives in
api/reactions.jsin the root of this repository. Vercel automatically detects theapi/folder and deploys any.jsfiles inside it as serverless endpoints. - The Endpoint: The live API is accessible at
https://haksoat-reactions-api.vercel.app/api/reactions.
3. Jekyll (The Frontend)
- The Code: The frontend widget is an HTML include located at
_includes/reactions.html. It contains the HTML structure, the CSS styling, and the vanilla JavaScript that interacts with the Vercel API. - Integration: This include is injected into the
_layouts/single.htmllayout, placing it at the bottom of every blog post.
How to View the Database
To see the raw reaction counts or modify them manually:
- Log in to console.upstash.com using your GitHub account (
HAKSOAT). - Click on the
haksoat-reactionsdatabase. - Click on the Data Browser tab on the left sidebar.
- Here, you will see a list of keys (e.g.,
reactions:lessons-from-my-father/). Click on a key to view the specific reaction counts for that post. - You can manually edit the counts directly in the Data Browser if needed.
How to View the API Logs
If the reactions feature stops working or you want to monitor traffic:
- Log in to vercel.com using your GitHub account (
HAKSOAT). - Click on the
haksoat-reactions-apiproject. - Click on the Logs tab in the top navigation menu.
- Here, you can see real-time logs of every HTTP request made to your API, including any errors or console output from the
api/reactions.jsfunction.
How to Modify the Feature
Changing the Reaction Types (e.g., adding a “Sad” reaction)
If you want to change the available reactions, you must update both the frontend and the backend.
1. Update the Backend (api/reactions.js)
Open api/reactions.js and locate the VALID_REACTIONS array:
const VALID_REACTIONS = ['like', 'love', 'insightful', 'curious'];
Add your new reaction to this array (e.g., 'sad').
2. Update the Frontend (_includes/reactions.html)
Open _includes/reactions.html and add a new button to the HTML structure:
<button class="reaction-btn" data-reaction="sad" aria-label="Sad"> 😢 <span class="reaction-count" id="count-sad">…</span></button>
Then, update the JavaScript array that initializes the counts:
['like', 'love', 'insightful', 'curious', 'sad'].forEach(function (r) { ... });
3. Deploy the Changes
- Commit and push the changes to the
masterbranch on GitHub. - The frontend changes will automatically deploy via GitHub Pages.
- The backend changes to
api/reactions.jswill automatically deploy to Vercel via a GitHub Actions workflow (.github/workflows/deploy-reactions.yml).
Changing the Styling
All CSS for the widget is contained within the <style> block inside _includes/reactions.html. You can modify colors, spacing, and typography there. These changes only require a standard git push to deploy via GitHub Pages.
How the Automated Deployment Works
We have set up a fully automated CI/CD pipeline using GitHub Actions to deploy the Vercel API.
The Trigger
The deployment is controlled by the .github/workflows/deploy-reactions.yml file. It is configured to only run when two conditions are met:
- A commit is pushed to the
masterbranch. - That commit includes changes to the
api/reactions.jsfile.
This ensures that regular blog post updates or CSS changes do not trigger unnecessary Vercel builds.
The Process
When the workflow triggers, it performs the following steps:
- Checks out the repository.
- Installs the Vercel CLI.
- Pulls the Vercel environment configuration using the
VERCEL_TOKENsecret. - Builds the project artifacts locally on the GitHub runner.
- Deploys the pre-built output directly to Vercel production.
The Secrets
The workflow relies on three repository secrets configured in GitHub (Settings > Secrets and variables > Actions):
VERCEL_TOKEN: The API token authorizing the deployment.VERCEL_ORG_ID: The Vercel team/account ID.VERCEL_PROJECT_ID: The specific Vercel project ID (haksoat-reactions-api).
You can monitor these deployments in the Actions tab of your GitHub repository or the Deployments tab in your Vercel dashboard.
Important Note on Renaming Posts
The reaction counts are tied to the URL slug of the blog post. If you change the URL of a post (e.g., from /old-title/ to /new-title/), the widget will look for counts under reactions:new-title/ and find nothing. Your old counts will still exist in the database under reactions:old-title/, but they will be orphaned.
To fix this, you must manually rename the key in the Upstash database:
- Go to the Upstash Data Browser.
- Open the CLI (Command Line Interface) at the bottom of the screen.
- Run the rename command:
RENAME reactions:old-title/ reactions:new-title/
Alternatively, set up a URL redirect in Jekyll so the old URL redirects to the new one, ensuring the slug remains consistent.
How did this post make you feel?