CommentKit
A tiny drop-in comment system for static sites. Paste 2 lines of code and you get threads, likes, and moderation.
I’ve written a handful of blogs now, and wanted to add a comment section. My first thought was to use Disqus — I’d seen it everywhere. But the free tier has ads, and the paid plans felt like overkill for a personal blog.
I looked at alternatives like Commento, Giscus, etc etc, but none really fit what I wanted.
So I built my own: CommentKit.
The Two-Line Integration
After you create and verify a site on commentkits dashboard, this is all it takes to add comments to your website:
<!-- Include the CommentKit bundle -->
<script src="https://commentkit.ankush.one/bundle.js"></script>
<!-- Add a div where you want comments -->
<div data-commentkit></div>
That’s it. No complex configuration, no API keys in your frontend code, no build steps. The widget automatically:
- Detects the current page URL
- Creates a page entry if it doesn’t exist
- Loads existing comments
- Handles user authentication
- Supports nested replies
Architecture Overview
CommentKit has two main parts: the embeddable widget that runs on your website, and a backend API that handles storage and authentication.
┌─────────────────┐ ┌──────────────────────┐ ┌─────────────┐
│ Your Website │◄───►│ Cloudflare Workers │◄───►│ D1 Database │
│ (bundle.js) │ │ (API Layer) │ │ (SQLite) │
└─────────────────┘ └──────────────────────┘ └─────────────┘
Embeddable Widget
When you add <script src="https://commentkit.ankush.one/bundle.js"> to your page, here’s what happens:
- The script finds all
<div data-commentkit>elements - It creates a hidden iframe pointing to the CommentKit domain
- The iframe handles authentication and loads comments
- Comments are rendered in place of the div on the host website
The tricky part is authentication. The widget runs on your website (myblog.com), but auth tokens need to be stored on the CommentKit domain. Cookies don’t work cross-domain, so I use an iframe with postMessage instead.
Your Website (bundle.js)
│
├── Creates hidden iframe → commentkit.ankush.one/widget
│
├── Sends messages via postMessage:
│ { action: 'loadComments', domain: 'myblog.com', pageId: '/post' }
│
└── Receives responses:
{ action: 'commentsLoaded', data: [...] }
The iframe acts as a secure bridge. All API calls happen inside the iframe, authenticating via HttpOnly cookies that are completely inaccessible to JavaScript — never exposed to the parent website or even the iframe itself.
The bundle.js is a single js file containing all the vanilla code needed to talk to the iframe and render comments.
The final bundle is around 70KB minified (12KB gzipped), self-contained with no external dependencies at runtime.
Backend
The API runs on Cloudflare Workers using Hono.js as the backend framework.
Data is stored in Cloudflare D1 — SQLite at the edge. The schema has tables for sites, pages, users, comments, reactions, and sessions.
Authentication uses magic links via Resend. When you log in, you enter your email, get a link, click it, and you’re in. No passwords to store or leak.
Security is handled through multiple layers: HttpOnly cookies for sessions (so tokens can’t be stolen via XSS), HMAC-signed CSRF tokens for all write operations, strict input sanitization that strips all HTML, and Content Security Policy headers that block inline scripts. Everything user-submitted is treated as plain text, not code
Dashboard
Site owners get access to a clean, functional dashboard:
- Overview Tab: Quick stats, recent activity, and analytics charts
- Sites Tab: Manage multiple sites, view comments by page, moderate content
- Settings Tab: Account settings, display name, and profile management
The dashboard is built with React and styled with a modern, minimal aesthetic using Tailwind CSS and Shadcn/ui components.
Why Cloudflare Workers?
I chose Cloudflare Workers for several reasons:
- Global edge deployment: Your API is served from the nearest datacenter to each user
- No cold starts: Workers are always warm and respond in milliseconds
- D1 integration: SQLite database with global replication, no separate database service needed
- Generous free tier: 100,000 requests/day for free
- Simple deployment:
wrangler deployand you’re live
Now What?
CommentKit is actively maintained and I’m planning several improvements:
- Email notifications when someone replies to your comment
- Markdown support in comments
- Spam detection
- Theming for customizing the widget appearance
- Webhooks for integrating with other services
Contributing
CommentKit is open to contributions! Whether it’s bug fixes, new features, or documentation improvements, check out the CONTRIBUTING.md for guidelines.
Try It Out
The best way to understand CommentKit is to try it. Check out the live demo or embed it on your own site. And if you find it useful, a star on GitHub would be much appreciated!
PS. You can even see commentkit in action at the bottom of this page! Leave a message.
All I did was add this html to this post, bundle.js is already in the head of the page.
<div data-commentkit></div>