A self‑hostable API service in Rust for tracking website visits and generating customizable SVG counters.
View Demo
·
Report Bug
·
Request Feature
Table of Contents
The Visit Counter API is a lightweight, self‑hostable backend service built in Rust using Rocket. It tracks website visits and dynamically generates SVG counters with customizable styling. This project is modularized as follows:
- SVG Generator Module: All SVG-generation logic is contained in
src/svg_generator.rs
. - External CSS: Styling is maintained in
assets/style.css
, allowing easy customization of colors, fonts, and borders. - API Endpoints: Endpoints are provided to get, increment, and set counter values, along with an SVG endpoint for embedding counters into webpages.
- Persistent Storage: Counter data is stored in
counters.json
via a file-based persistence module (src/persistent_counter.rs
), ensuring counters are preserved across API restarts.
If you simply want to utilize my API, you can simply add an img
tag to your site:
<img
src="https://visitcounter.aichan.ovh/counter/YOUR_PAGE_NAME/svg?label=YOUR_TEXT&color=YOUR_COLOR&style=font-weight:bold;"
alt="Visit Counter" />
- Page name: Don't forget to set it
https://visitcounter.aichan.ovh/counter/YOUR_PAGE_NAME...
label
: The text shown to the left.style
: Directly embed CSS in here. Something like":root { --background-counter: red; }"
would work.
Tip
If you intend to use this in GitHub, make sure you encode all spaces with %20
. HTML URL Encoding Reference
The style is controlled with the CSS variables defined assets/style.css
. These constants can also be modified to adjust the appearance:
-
SVG Dimensions:
width
: Overall width of the SVG (default: 150).height
: Overall height of the SVG (default: 20).label_width
: Width of the left section (label background) (default: 100).counter_width
: Width of the right section (counter background) (default: 50).radius
: Border radius for rounded corners (default: 3).
-
Gradient Settings:
grad_stop1_color
: Color of the first gradient stop (default: #bbb).grad_stop1_opacity
: Opacity of the first gradient stop (default: 0.1).grad_stop2_opacity
: Opacity of the second gradient stop (default: 0.1).
-
Text Settings:
font_family
: Font family used for the counter text (default: 'Metrophobic', 'Comfortaa', sans-serif).font_size
: Font size for the text (default: 11).label_offset_x
: X-coordinate for the label text (default: 50).label_offset_y
: Y-coordinate for the label text (default: 15).counter_offset_x
: X-coordinate for the counter text (default: 125).counter_offset_y
: Y-coordinate for the counter text (default: 15).shadow_fill
: Color used for the text drop shadow (default: #010101).shadow_opacity
: Opacity of the text drop shadow (default: 0.3).
-
Color Settings (NyakoTech Inspired):
background_label
: Background for the label section (default: #18181b).background_counter
: Background for the counter section (default: #DC26B6).label_color
: Color of the label text (default:#fff).counter_color
: Color of the counter text (default:#fff).
The project is organized as follows:
visit_counter/
├── Cargo.toml
├── .env # Environment variables file (optional)
├── assets/
│ └── style.css # External CSS for SVG styling
└── src/
├── main.rs # Main application with API endpoints
├── models.rs # Data structures
├── svg_generator.rs# Module for generating SVG content
└── persistent_counter.rs # Module for file-based persistent storage
- models.rs: Contains data structures for counters and SVG options.
- svg_generator.rs: Provides the
generate_svg
function that creates the SVG output. - main.rs: Defines API endpoints, loads environment variables, and integrates all modules.
Follow these instructions to set up a local instance of the Visit Counter API.
- Rust installed
- Cargo (bundled with Rust)
- (Optional) Docker if you plan to deploy in a container
-
Clone the repository:
git clone https://github.com/AitorAstorga/visit_counter.git cd visit_counter
-
(Optional) Create a
.env
file in the project root: This file should define your API key:API_KEY=your_secret_api_key_here
-
Run the application locally:
export API_KEY=your_secret_api_key_here # if not using `.env` cargo run
By default, Rocket runs on localhost:8000
.
You can test the endpoints using your browser, curl, or any HTTP client.
-
GET Counter Value (JSON):
curl http://localhost:8000/api/counter/test
-
Increment Counter (JSON):
curl -X POST http://localhost:8000/api/counter/test/increment
-
Set Counter Value (JSON, Requires API Key):
curl -X PUT http://localhost:8000/api/counter/test \ -H "Content-Type: application/json" \ -H "x-api-key: your_secret_api_key_here" \ -d '{"count": 123}'
-
SVG Counter Endpoint: Open your browser or use curl:
curl "http://localhost:8000/counter/test/svg?label=Page%20Views&color=ff5733&style=font-weight:bold;"
This returns an SVG image with your counter, which you can embed using an
<img>
tag.
If you prefer containerized deployment, you can use Docker.
A sample
# Use an official Rust image as the builder.
FROM rust:1.70 as builder
WORKDIR /app
COPY Cargo.toml Cargo.lock ./
COPY src/ ./src/
COPY assets/ ./assets/
RUN cargo build --release
# Use a minimal image for the final binary.
FROM debian:buster-slim
COPY --from=builder /app/target/release/visit_counter /usr/local/bin/
EXPOSE 8000
CMD ["visit_counter"]
A sample
version: "3"
services:
counter:
container_name: visit-counter
image: ghcr.io/aitorastorga/aichan-visit-counter:latest
ports:
- "8000:8000"
environment:
ROCKET_ADDRESS: "0.0.0.0"
ROCKET_PORT: "8000"
API_KEY: "your_secret_api_key_here"
volumes:
- /PATH_TO_YOUR_DATA:/data
Contributions are welcome! Please fork the repository, make your changes, and open a pull request.
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/AmazingFeature
) - Commit your Changes (
git commit -m 'Add some AmazingFeature'
) - Push to the Branch (
git push origin feature/AmazingFeature
) - Open a Pull Request
Distributed under the European Union Public License v1.2. See LICENSE
for more information.
Aitor Astorga Saez de Vicuña - [email protected]
Project Link: https://github.com/AitorAstorga/visit_counter
This is based on Anton Komarev's github-profile-views-counter, but made in Rust.