Skip to content
Vincent's Notes
Go back

Building a Cloudflare-Native Comment System for Hugo

by Vincent Yang Made with AI

I finally replaced my old comment setup and moved everything to a new system built by myself.

The result is simple: my blog is now fully running on Cloudflare.

This post explains why I migrated from Artalk, what I built, and how the migration worked.

Why I Migrated from Artalk

Artalk is a great project, and it worked well for me for a long time. I used it as a reference while redesigning my own system.

But I wanted tighter control over:

So instead of extending Artalk, I built a focused API-first comment service for my own use case.

Architecture

The current architecture is intentionally minimal.

  1. The blog frontend sends requests to a comment API endpoint.
  2. Cloudflare Workers handles validation, moderation, and notification.
  3. D1 stores pages, comments, threading metadata, and moderation state.
  4. Telegram Bot receives new-comment notifications for moderation and admin replies.

The frontend is custom, integrated into my Hugo theme, and styled to keep the previous reading experience close to what I had before.

Core Features

1) API-first comment service

No separate admin panel or heavy UI dependency in the backend. The Worker exposes clean endpoints for posting comments, listing comments, and stats.

2) Threaded comments with pagination

Each comment keeps parent_id, root_id, and depth, and public listing supports page-based pagination.

3) Flexible moderation

AUTO_APPROVE controls default behavior:

In both modes, Telegram notifications are sent.

4) Admin identity and anti-impersonation

Reserved admin emails are blocked from public submission, so regular users cannot pretend to be the site owner.

5) Gravatar and metadata

Avatar URLs are generated from email via Gravatar hash.

For network metadata, the system uses api.ipinfo.es and stores country, ASN, and related fields in D1. Country display uses full country name and a separate country code for flags.

6) Consistent timestamps

API timestamps are normalized to include timezone offsets, so old imported comments and new comments use a consistent format.

Migration from Artalk

I migrated historical comments from an Artalk export file (.artrans) into D1.

High-level process:

  1. Export data from the old Artalk instance.
  2. Convert .artrans to D1-compatible SQL with a converter script.
  3. Apply schema migrations on D1.
  4. Import SQL into D1.
  5. Run normalization migrations (owner identity, metadata fixes).
  6. Verify thread structure, timestamps, and moderation state.

This gave me a smooth transition without losing old threads.

Why This Stack Fits My Blog

I wanted one platform for everything.

Now the entire blog stack is inside Cloudflare:

No extra VM, no extra database vendor, no mixed ops stack.

Final Notes

This system is built for my blog first, but the architecture is reusable.

The most important part for me is that I now control the full comment pipeline end to end: data model, moderation workflow, frontend behavior, and deployment.

Migrating from Artalk was straightforward once the converter and D1 migrations were in place.


Share this post:

Previous Post
Is OpenClaw Better for Developers or Non-Technical Users?
Next Post
JR East Japan Billing Issue

Comments 0

Finished reading? Why not leave a word.