DEV Community

Anders Dahl Rasmussen
Anders Dahl Rasmussen

Posted on

I built ReviewReply in 48 hours — Cloudflare Worker + Claude AI + Stripe, $0/month infrastructure

I built ReviewReply in 48 hours — $0/month infrastructure

Every restaurant owner I know dreads bad reviews. Not because the criticism stings — because responding well takes time they don't have.

So I built ReviewReply — paste any Google, TripAdvisor or Airbnb review, get a professional AI-generated response in 10 seconds. Free tier, no sign-up, no friction.

Here's the full stack breakdown.

The architecture (everything runs free)

Cloudflare Worker → rate limiting + AI calls + Telegram cron
Cloudflare KV     → rate limiting per IP (3/day free)
Cloudflare Pages  → static frontend
Anthropic Claude  → Haiku for replies, Sonnet for full audits
Brevo             → transactional email (300/day free tier)
Stripe            → payment links (no checkout page needed)
Enter fullscreen mode Exit fullscreen mode

Total monthly cost for zero traffic: $0. For moderate traffic (thousands of API calls): still $0.

The worker (the whole backend in one file)

The core is a Cloudflare Worker with 4 endpoints:

// POST /reply — generate professional review response
// POST /mini-audit — free sentiment preview
// POST /audit — full paid audit ($29), email delivery
// POST /activate-pro — Stripe session → Pro token
Enter fullscreen mode Exit fullscreen mode

Rate limiting is handled server-side via KV — no localStorage, no client trust:

async function getRate(env, type, ip) {
  const date = new Date().toISOString().split('T')[0];
  const key = `rate:${type}:${ip}:${date}`;
  const count = parseInt(await env.RR_RATE.get(key) || '0');
  return { key, count };
}
Enter fullscreen mode Exit fullscreen mode

Pro activation without webhooks

Most tutorials tell you to set up Stripe webhooks. I skipped that entirely.

// 1. Capture email BEFORE redirecting to Stripe
sessionStorage.setItem('proEmail', email);
window.location.href = STRIPE_PAYMENT_LINK;

// 2. On page load, check for session_id in URL
const sessionId = params.get('session_id');
if (sessionId?.startsWith('cs_live_')) {
  const email = sessionStorage.getItem('proEmail');
  await fetch(WORKER_URL + '/activate-pro', {
    body: JSON.stringify({ session_id: sessionId, email })
  });
}
Enter fullscreen mode Exit fullscreen mode

The worker validates cs_live_ prefix, generates a UUID token, stores it in KV. No webhook infrastructure needed.

The Telegram cron (passive audience building)

# wrangler.toml
[triggers]
crons = ["0 8 * * *"]
Enter fullscreen mode Exit fullscreen mode
export default {
  async scheduled(event, env, ctx) {
    ctx.waitUntil(postDailyTip(env));
  }
};
Enter fullscreen mode Exit fullscreen mode

Every morning at 08:00 UTC, the worker posts a review management tip to Telegram automatically. Zero ongoing maintenance.

The full audit (ReviewScan — $29)

For the paid audit, I use Claude Sonnet instead of Haiku:

const content = await callClaude(
  env, systemPrompt, reviewText,
  'claude-sonnet-4-6' // Quality over speed for paid features
);
Enter fullscreen mode Exit fullscreen mode

The audit includes: sentiment score, top 5 complaint categories with frequency %, 20 ready-to-use reply templates, and a 30-day action plan. All delivered via Brevo email within 2 minutes.

What I learned

  • Cloudflare Workers are genuinely fast — cold start is sub-1ms, which matters for UX
  • No-registration free tiers convert better than email-gated ones (friction kills trials)
  • Brevo over SendGrid/Mailgun for small volume — 300 free emails/day with real deliverability
  • Skip webhooks when you can — the session_id pattern is simpler and equally secure for payment links

Try it

reviewreply.pages.dev — 3 free replies/day, no sign-up

Feedback welcome. Built this as part of a larger suite of AI tools for local businesses under the BaseAI umbrella.

Top comments (0)