Quick start
StaticLayer adds comments, reactions and polls to any static site — deployed into your own Cloudflare account. You need a Cloudflare account and, for the CLI path, Node.js ≥ 20.
Moderated conversations
Nested threads, likes, pin, sorting — all plain-text and privacy-safe.
02 · ReactionsAnonymous emoji counts
One-tap reactions with proof-of-work integrity and escalating difficulty.
03 · PollsPrivate StrawPoll-style votes
Single or multi-select, ranked results, embed anywhere — even globally.
How it works — technically
When a visitor loads a page with the widget, the browser calls your Worker to get a signed, single-use challenge, solves a small Proof-of-Work (so spam has a real cost, without any CAPTCHA), and submits the comment with its proof. The Worker verifies the signature and the proof, consumes the challenge atomically (a D1 batch — one challenge can never be reused, even under races), and stores the comment as pending in your D1 database. An admin approves it from /admin.html and it appears on the page.
Visitor browser Your Cloudflare account
─────────────── ─────────────────────────
widget.js Worker (runtime) D1 (database)
│ GET /api/comments/challenge → │ │
│ ← signed challenge (HMAC) │ │
│ solve Proof-of-Work ─┐ │ │
│ POST /api/comments │ │ verify sig + PoW │
│ (comment + nonce) ────────────→│ consume challenge │
│ │ store as pending │
│ approve from /admin.html │ → status: approved │
No cookies, no IP, no tracking
The public widget stores nothing in the browser; the runtime never persists IPs or fingerprints.
Cost, not identity
Proof-of-Work + honeypot + a 3-second time gate. No CAPTCHA, no friction for readers.
BYOC
Everything runs in your Cloudflare account — Worker, D1 database, secrets. No central platform.
Why installation is easy
There are three ways to install — pick the one that fits you:
Zero terminal
The hosted browser installer deploys Worker + D1 + secrets into your account in a few clicks — nothing stored on disk.
One command
npx staticlayer init observes, plans, applies and verifies the whole deployment for you.
Full control
Create the Worker and D1 in the Cloudflare dashboard yourself — the universal guide walks through every step.
1 · Prepare credentials
Create an API token in the Cloudflare dashboard with account permissions Workers Scripts: Edit, Cloudflare D1: Edit and Account Settings: Read. Copy your Account ID from the same dashboard.
2 · Install & generate secrets
npm install
npm run build
export CLOUDFLARE_API_TOKEN="<your token>" # never stored on disk
export STATICLAYER_ADMIN_SECRET="$(openssl rand -hex 32)"
export STATICLAYER_SESSION_SECRET="$(openssl rand -hex 32)"
export STATICLAYER_POW_SECRET="$(openssl rand -hex 32)"
3 · Deploy
npx staticlayer init # observe → plan → apply → verify
# then create the D1 tables
npx wrangler d1 migrations apply staticlayer --remote -c wrangler.jsonc
4 · Add the widget
<div data-staticlayer data-api="https://comments.example.com"></div>
<script src="https://comments.example.com/widget.js" defer></script>
The same snippet works on every page (thread = page URL). Add an anonymous reaction bar with data-reactions="👍,❤️,🎉", show it without comments via data-reactions-only, embed a poll with data-poll-id, enable replies (up to 3 levels) or place the reactions above the comments — see Integrations.
5 · Moderate
Open https://comments.example.com/admin.html, sign in with ADMIN_SECRET (or password-less with GitHub OAuth — guide inside the admin under Settings → Admin access & sign-in), and approve the first comment.