Update with hugo setup instructions
This commit is contained in:
parent
97e21bcb9b
commit
6979e73307
1 changed files with 110 additions and 1 deletions
111
README.md
111
README.md
|
|
@ -4,7 +4,9 @@ upvoters is a basic anonymous voting system that can be added to a blog.
|
||||||
I recently reworked my personal blog with the Hugo Bear blog theme.
|
I recently reworked my personal blog with the Hugo Bear blog theme.
|
||||||
I came across the [creator's (Herman Martinus) blogging site](https://herman.bearblog.dev/) which had this really cool anonymous upvote system.
|
I came across the [creator's (Herman Martinus) blogging site](https://herman.bearblog.dev/) which had this really cool anonymous upvote system.
|
||||||
I wanted something similar and decided to implement it myself.
|
I wanted something similar and decided to implement it myself.
|
||||||
The goal is maximum simplicity.
|
The goal is maximum simplicity so that I can use it with my Hugo static site.
|
||||||
|
It's directly integrated in [my theme]("https://forge.alexselimov.com/aselimov/hugo-bearcub") which attempts to mimic Herman Martinus' bear blog style.
|
||||||
|
I've added steps on how I set it up in my theme [at the bottom of this README](#setting-it-up-with-hugo).
|
||||||
|
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
@ -15,6 +17,7 @@ The goal is maximum simplicity.
|
||||||
- [API](#api)
|
- [API](#api)
|
||||||
- [Running tests](#running-tests)
|
- [Running tests](#running-tests)
|
||||||
- [Actual deployment](#actual-deployment)
|
- [Actual deployment](#actual-deployment)
|
||||||
|
- [Setting it up with Hugo](#setting-it-up-with-hugo)
|
||||||
- [License](#license)
|
- [License](#license)
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
@ -161,6 +164,112 @@ sudo systemctl enable --now upvoters
|
||||||
curl https://example.com/api/posts/tests/votes
|
curl https://example.com/api/posts/tests/votes
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Setting it up with Hugo
|
||||||
|
|
||||||
|
I set this up in my [Voting Bear Cub Theme](https://forge.alexselimov.com/aselimov/hugo-bearcub/src/branch/main).
|
||||||
|
The components are:
|
||||||
|
1. Javascript file to handle upvoting. This function is automatically called on page loads
|
||||||
|
```javascript
|
||||||
|
|
||||||
|
(async function () {
|
||||||
|
// Define the slug
|
||||||
|
const slug = location.pathname.replace(/^\/|\/$/g, "").replaceAll("/", "-");
|
||||||
|
const API = window.UPVOTE_API;
|
||||||
|
|
||||||
|
const btn = document.getElementById("upvote-btn");
|
||||||
|
const count = document.getElementById("upvote-count");
|
||||||
|
|
||||||
|
// On load fetch curent vote count and whether the button should be clicked on or off
|
||||||
|
const res = await fetch(`${API}/posts/${slug}/votes`, {
|
||||||
|
credentials: "include",
|
||||||
|
});
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
count.textContent = data.vote_count;
|
||||||
|
if (data.voted) btn.setAttribute("voted", true);
|
||||||
|
|
||||||
|
btn.addEventListener("click", async () => {
|
||||||
|
const alreadyVoted = btn.hasAttribute("voted");
|
||||||
|
|
||||||
|
const method = alreadyVoted ? "DELETE" : "POST";
|
||||||
|
const r = await fetch(`${API}/posts/${slug}/vote`, {
|
||||||
|
method,
|
||||||
|
credentials: "include",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (r.ok) {
|
||||||
|
const updated = await fetch(`${API}/posts/${slug}/votes`, {
|
||||||
|
credentials: "include",
|
||||||
|
});
|
||||||
|
const d = await updated.json();
|
||||||
|
count.textContent = d.vote_count;
|
||||||
|
if (d.voted) btn.setAttribute("voted", false);
|
||||||
|
else btn.removeAttribute("voted");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
```
|
||||||
|
2. Button component in single.html template placed after the main post body. **Note:** I guard this behind a config check so users can use my theme without setting up upvoters.
|
||||||
|
```html
|
||||||
|
{{ if .Site.Params.upvotes }}
|
||||||
|
<div class="upvote">
|
||||||
|
<button id="upvote-btn" aria-label="Upvote">
|
||||||
|
<span id="upvote-chevron">⌃</span>
|
||||||
|
<span id="upvote-count">—</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<script>window.UPVOTE_API = "{{ .Site.Params.upvoteApi }}";</script>
|
||||||
|
<script src="/upvote.js"></script>
|
||||||
|
{{ end }}
|
||||||
|
```
|
||||||
|
3. Styles for the button:
|
||||||
|
```css
|
||||||
|
.upvote {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
width: fit-content;
|
||||||
|
gap: 0.2rem;
|
||||||
|
margin-block: var(--spacing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#upvote-btn {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
color: currentColor;
|
||||||
|
font-size: calc(var(--size) * 4);
|
||||||
|
line-height: 0.8;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0;
|
||||||
|
opacity: 0.4;
|
||||||
|
transition: opacity 0.15s, color 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#upvote-btn:hover {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
#upvote-btn[voted] {
|
||||||
|
color: var(--color-primary);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#upvote-chevron {
|
||||||
|
display: block;
|
||||||
|
line-height: 1;
|
||||||
|
margin-bottom: -0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#upvote-count {
|
||||||
|
font-size: calc(var(--size) * 1.6);
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
MIT — see [LICENSE](LICENSE).
|
MIT — see [LICENSE](LICENSE).
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue