2026-03-19 15:52:48 -04:00
|
|
|
# upvoters ☝️
|
2026-03-17 09:38:52 -04:00
|
|
|
|
2026-03-19 15:52:48 -04:00
|
|
|
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 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.
|
|
|
|
|
The goal is maximum simplicity.
|
|
|
|
|
|
|
|
|
|
## Important Notes
|
|
|
|
|
|
|
|
|
|
This service does NOT have any authentication/authorization, so you should NOT serve this to the public web.
|
|
|
|
|
I'm using this by just serving it on the same VPS as my blog.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Requirements
|
|
|
|
|
|
|
|
|
|
- Rust (stable)
|
|
|
|
|
- PostgreSQL 16
|
|
|
|
|
|
|
|
|
|
## Configuration
|
|
|
|
|
|
|
|
|
|
The following environment variables are required:
|
|
|
|
|
|
|
|
|
|
| Variable | Description |
|
|
|
|
|
|------------------------------|----------------------------------------------------------------------------------------|
|
|
|
|
|
| `POSTGRES_CONNECTION_STRING` | PostgreSQL connection string (e.g. `postgres://user:password@localhost:5432/upvoters`) |
|
|
|
|
|
|
|
|
|
|
## Running locally
|
|
|
|
|
|
|
|
|
|
### With Docker Compose
|
|
|
|
|
|
|
|
|
|
Builds and starts both the database and app:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
docker compose up --build
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The server will be available at `http://localhost:3000`.
|
|
|
|
|
|
|
|
|
|
### Without Docker
|
|
|
|
|
|
|
|
|
|
Start the database:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
docker compose up -d db
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Run the server:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
POSTGRES_CONNECTION_STRING=postgres://uprs:password123@localhost:5432/uprs cargo run
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The server listens on port `3000`.
|
|
|
|
|
|
|
|
|
|
## API
|
|
|
|
|
|
|
|
|
|
| Method | Endpoint | Description |
|
|
|
|
|
|---|---|---|
|
|
|
|
|
| `GET` | `/health` | Health check |
|
|
|
|
|
| `POST` | `/posts/{slug}/vote` | Upvote a post |
|
|
|
|
|
| `DELETE` | `/posts/{slug}/vote` | Remove a vote from a post |
|
|
|
|
|
| `GET` | `/posts/{slug}/votes` | Get vote count and whether the current user has voted |
|
|
|
|
|
|
|
|
|
|
Voter identity is tracked via a `voter_id` cookie. One is set automatically on first request.
|
|
|
|
|
|
|
|
|
|
### `GET /posts/{slug}/votes` response
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
{
|
|
|
|
|
"vote_count": 42,
|
|
|
|
|
"voted": true
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Running tests
|
|
|
|
|
|
|
|
|
|
Tests require a running PostgreSQL instance at `postgres://uprs:password123@localhost:5432/uprs`.
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
cargo test
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## License
|
|
|
|
|
|
|
|
|
|
MIT — see [LICENSE](LICENSE).
|