Skip to content

Getting Started

Yang Chun (陽春 — meaning “simple and unadorned”) Comment is a lightweight, privacy-first commenting system built with Lit and Hono, designed to run on Cloudflare Workers. No registration required and no personal data is stored—ideal for small sites and blogs.

✨ Features:

  • No login
  • No cookies
  • No personal data collection
  • No browser fingerprinting*

About fingerprinting Currently we use a hashed IP for backend rate limiting. This provides partial identifiability but is not equivalent to full browser fingerprinting:

  1. Multiple users on public networks can share the same IP.
  2. A single user may have different IPs due to ISP dynamic addressing.

An IP cannot uniquely identify a person. In the future we may consider a Proof-of-Work approach to reduce malicious traffic while avoiding hashed IPs.

# Clone
git clone https://github.com/ziteh/yangchun-comment.git
cd yangchun-comment
# Install dependencies and build
pnpm install
pnpm build
# Move to server folder
cd server

Create a KV namespace (comments data stored here):

pnpm exec wrangler kv namespace create "yangchun-comment-kv"

Example response (you’ll get an id to copy):

...
🌀 Creating namespace with title "yangchun-comment-kv"
Success!
To access your new KV Namespace in your Worker, add the following snippet to your configuration file:
[[kv_namespaces]]
binding = "yangchun_comment_kv"
id = "506ac68ae906458692g22933d3896af3"

Update your wrangler.toml and replace the id value with the one returned above:

wrangler.toml
...
[[kv_namespaces]]
binding = "COMMENTS"
id = "506ac68ae906458692g22933d3896af3" # Replace with your KV ID
...
# You may modify these values as needed
[vars]
FRONTEND_URL = "https://your-frontend-url.com" # Frontend URL
CORS_ORIGIN = "*" # CORS origin, use "*" to allow all origins
RSS_SITE_PATH = "site" # The path for the all-site RSS feed
ADMIN_USERNAME = "admin" # Admin username
MAX_MSG_LENGTH = 1000 # The max length of the comment message in characters
MAX_PSEUDONYM_LENGTH = 80 # The max length of the pseudonym in characters
MAX_ALL_SITE_RSS_COMMENTS = 25 # The max number of comments in the all-site RSS feed

Deploy to Cloudflare Workers:

pnpm run deploy

You should see an endpoint like:

...
Uploaded yangchun-comment-be (3.75 sec)
Deployed yangchun-comment-be triggers (0.94 sec)
https://yangchun-comment-be.<YOUR_SUBDOMAIN>.workers.dev
Current Version ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

Update Secrets. You need to set a security key for HMAC_SECRET_KEY and ADMIN_SECRET_KEY. The value should be a strong random string that is long enough (at least 32 char is recommended). You can use a tool like this, this or this to generate a random key. Also set the admin password ADMIN_PASSWORD.

Use the wrangler secret put to set the secret, which will start the interactive operation and prompt you to enter the value.

# HMAC secret key
pnpm exec wrangler secret put "HMAC_SECRET_KEY"
# Admin JWT signature key
pnpm exec wrangler secret put "ADMIN_SECRET_KEY"
# Admin login password
pnpm exec wrangler secret put "ADMIN_PASSWORD"

Once completed, you can test it by visiting https://yangchun-comment-be.<YOUR_SUBDOMAIN>.workers.dev/rss/<RSS_SITE_PATH>, which is an RSS feed and will return XML content. Note that the URL does NOT have a trailing slash.

Install the client package.

pnpm add @ziteh/yangchun-comment-client

Add to your project:

// React example
import { useEffect, useRef } from 'react';
import '@ziteh/yangchun-comment-client';
import '@ziteh/yangchun-comment-client/style.css';
const API_URL = 'https://yangchun-comment-be.<YOUR_SUBDOMAIN>.workers.dev';
function App() {
const wcRef = useRef<HTMLElement | null>(null);
useEffect(() => {
if (!wcRef.current) return;
(wcRef.current as any).apiUrl = API_URL;
(wcRef.current as any).authorName = 'Test Author';
(wcRef.current as any).post = '/blog/my-post';
}, []);
return (
<div>
<yangchun-comment ref={wcRef}></yangchun-comment>
</div>
);
}
export default App;