Repo of the Day
KingPin/Garrul
Published: Oct 12, 2026
Open repository ↗Self-hosted comments for static sites, Cloudflare Workers + D1 + KV + Turnstile, threaded, OAuth, embeddable widget
Summary
Garrul is a self-hosted comments service for static sites and blogs, written in TypeScript and deployed to Cloudflare Workers with D1, KV, and Turnstile. It exposes an embeddable widget with threaded comments, OAuth sign-in, and an admin UI, all driven by a single Worker running in your own Cloudflare account.
What it is useful for
Garrul is a fit when you want reader comments on a static site but don't want to operate a container, a VPS, or a database server. The README frames its model as "one Worker per site, no per-comment billing, your data stays in your account." Concretely, it provides:
- Threaded comments with markdown, reactions, an edit/delete window, and newest/oldest/top sorting
- OAuth sign-in via GitHub, Google, Facebook, X, or Discord, plus rate-limited anonymous posting gated by Turnstile
- An embeddable widget documented as capped at 30 KB gzipped and isolated in a Shadow DOM, with an iframe fallback
- Reply and moderator email digests via Resend (off by default), webhook out to Slack/Discord/Telegram, and a Telegram operator bot
- An anti-spam layer that is always on: sliding-window rate limit, strict markdown sanitizer (no raw HTML, no images, links
nofollow ugc noopener), a hidden honeypot, and optional heuristics plus an Akismet or Workers AI classifier. Nothing is auto-deleted — every layer routes to a moderation queue - Migration paths from Disqus (
.xml.gz), Remark42 (userbackup-…gz), and Comentario JSON, with isso and Cusdis handled by a SQLite dump step. Re-runs are idempotent.
Access is gated by an ALLOWED_ORIGINS allowlist (no wildcards) on /api/*. Browser fetches carry Origin automatically; direct curl-style hits return 403 err.origin.forbidden.
How engineers can use it
For a local dry run, the README ships working dev defaults including Cloudflare's "always passes" Turnstile test keys:
git clone https://github.com/KingPin/Garrul.git
cd Garrul
npm install
cp wrangler.example.toml wrangler.toml
cp .dev.vars.example .dev.vars
npm run migrate
npm run dev
For production, npm run setup asks two questions and creates the resources, secrets, hostname, migrations, and deploy. Upgrades run npm run upgrade, with --dry-run supported. Embedding is a <div> carrying data-slug, data-api, data-title, data-url, and data-published plus a single embed.js script tag; recipes for Astro, Hugo, Jekyll, WordPress, and plain HTML live in examples/README.md.
A few operational caveats from the docs: Safari readers need HTTPS because the auth cookie is SameSite=None; Secure; Partitioned, and *.workers.dev is not meant for production — map a custom subdomain. The admin UI lives at /admin and is reachable by OAuth identities whose email is in ADMIN_EMAILS.