The backend for c.stupid.cat. A few small Cloudflare Workers that power the site's Discord presence, guestbook, and contribution heatmap. Everything here is read-mostly, CORS-open, and documented below.
Discord presence + profile/badges, in one unified shape.
A combined presence API (Lanyard-style) and profile & badges API (dstn.to-style), served from a single Cloudflare Worker + Durable Object and backed by one Discord bot. It exposes a REST endpoint and a Lanyard-compatible WebSocket, returning the same unified JSON either way. Presence is only visible for users who share a server with the bot, same model as Lanyard.
| GET/ | Service info + endpoint list. |
| GET/v1/users/:id | Unified record | presence + profile + badges + connected accounts. |
| GET/v1/users/:id/presence | Presence only (status, activities). |
| GET/v1/users/:id/profile | Profile + badges only. |
| WS/socket | WebSocket stream (Lanyard protocol). /ws works too. |
:id is a Discord snowflake. Add ?fresh=1 to bypass the cache and force a live refetch.
# unified record curl https://restful.doughmination.uk/v1/users/1226207941484646401
{
"success": true,
"data": {
"user": { "id": "…", "username": "clove" },
"presence": { "status": "online" },
"badges": [ … ],
"source": { "presence": "gateway" }
}
}
The guestbook behind c.stupid.cat, no database, just KV.
A tiny Worker that stores guestbook entries as a single JSON array in Workers KV,
think of it as a JSON file living on Cloudflare's edge. Read entries with pagination, or post a new
one. Spam is kept out with a honeypot field (url2, leave it empty),
a per-IP rate limit, and optional Turnstile captcha.
| GET/?limit=50&offset=0 | List entries, newest first. Returns { entries, total, limit, offset }. |
| POST/ | Add an entry. JSON body: { name, message, website?, turnstileToken?, url2? }. |
Field limits: name ≤ 40, message ≤ 500, website ≤ 200 chars. Stored as plain text, the page renders it, never the API.
curl 'https://guestbook.doughmination.uk/?limit=2'
{
"entries": [
{
"id": "…",
"name": "Clove",
"message": "hi from the edge!",
"ts": 1750000000000
}
],
"total": 1, "limit": 2, "offset": 0
}
curl -X POST https://guestbook.doughmination.uk/ \ -H 'Content-Type: application/json' \ -d '{"name":"Clove", "message":"hello!"}'
One contribution heatmap, merged from every forge.
A tiny, extensible Worker that pulls contribution calendars from GitHub and any number of Forgejo instances (git.gay, Codeberg, …) and merges them into one JSON object, keyed by source. The site uses it to draw a single heatmap that counts commits everywhere, not just GitHub. Responses are cached at the edge for an hour.
| GET/ | Merged heatmap. One key per forge; each is an array of { timestamp, contributions } days. Cached 1h. |
curl https://contrib.doughmination.uk/
{
"github": [
{ "timestamp": 1750032000,
"contributions": 4 }
],
"gitdotgay": [
{ "timestamp": 1750032000,
"contributions": 2 }
]
}