Dev.to WebDev 🛠 Dev 👁 0 📖 1 min read

Building a rate-limited blog thread AI tool on Cloudflare Workers (no login, no DB)

I built Blog2Thread — paste a blog URL or text, get a ready-to-post X/Twitter thread. No account. No database of users. Why no-login draft tools win for indie makers Most "blog to thread" tools either: forc

I built Blog2Thread — paste a blog URL or text, get a ready-to-post X/Twitter thread. No account. No database of users.

Why no-login draft tools win for indie makers

Most "blog to thread" tools either:

  • force signup before you see output, or
  • gate voice-training / scheduling behind paywalls

For the draft step, that friction is wrong. I want: paste → draft → copy. Scheduling and voice memory belong in paid tools (Typefully, Hypefury, etc.) after you have text.

Stack

  • Next.js 15 (App Router)
  • OpenNext → Cloudflare Workers
  • Cloudflare KV for counters (no user DB)
  • OpenAI-compatible API for generation

Rate limit design (cookie + IP + burst)

Anonymous abuse is the main risk. Caps today:

Bucket Limit
Per browser cookie (b2t_aid) 5 generates / day
Per IP 25 generates / day
Burst per IP 4 / ~2 min

URL-fetch has its own (slightly higher) buckets so reading a page ≠ generating a thread.

Pattern: reserve before generate → rollback if the model call fails, so failed runs don't burn the daily quota.

Pseudo-flow (simplified, no secrets):

const reservation = await reserveGenerateLimit(req);
if (!reservation.ok) return 429;

try {
  const thread = await callModel(...);
  return ok(thread);
} catch (e) {
  await reservation.rollback();
  throw e;
}

Cookie is the hard per-person cap; IP is looser so one office NAT doesn't nuke everyone.

Dynamic OG on share pages

/thread/{id}/ is noindex (don't submit those to GSC), but humans can open them.

generateMetadata builds title/description from tweet 1–4 of the saved draft, so X cards preview the hook — not a generic site title.

Honest limitations

  • No scheduling / auto-post
  • No voice training
  • Affiliate links only on the "go schedule / distribute" step — draft stays free
  • Self-fetch of some URLs still fails (bot/CF); paste-text always works

Try it

Feedback welcome — especially bad hooks and over-emoji drafts.

📰 Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.