Dev.to AI 🤖 Ai 👁 0 📖 3 min read

I updated our drug profile to 563-drug harm-reduction library in 9 languages on Cloudflare's free tier — here's the stack

Every year, millions of people Google things like "what does fentanyl look like" or "can you mix Xanax and alcohol" — and land on forum speculation. I built plugreports to fix that: a free harm-reduction library with 563

I updated our drug profile to 563-drug harm-reduction library in 9 languages on Cloudflare's free tier — here's the stack

Every year, millions of people Google things like "what does fentanyl look like" or "can you mix Xanax and alcohol" — and land on forum speculation. I built plugreports to fix that: a free harm-reduction library with 563 plain-language drug profiles, 61 mixing-danger guides, verified hotlines across nine regions, and an identification video library — in nine languages.

The interesting part (this is dev.to): the whole thing runs on Cloudflare's free tier. Here's how.

The architecture

Static generation, but with a CMS. A dependency-free Python script (build.py) reads plain data_*.py files and emits ~1,100 static HTML pages — every drug profile, guide, comparison and data page — with full JSON-LD (MedicalWebPage, FAQPage, BreadcrumbList), honest lastmod sitemaps, and real bidirectional hreflang clusters. No framework, no build step beyond python3 build.py.

A KV-backed admin CMS on Pages Functions. Static doesn't mean frozen. A PIN-protected /admin panel (HMAC-token auth against a Pages Function) edits every collection into a Cloudflare KV namespace. Pages Functions serve each route: if the slug exists as a static file it's served directly, and a small hydrate.js overlays any admin edits from KV onto the static page at runtime. Admin-created items that don't exist statically get rendered client-side. KV always wins over the seed data — reseeding never clobbers an admin edit.

Edge SEO injection. KV-rendered pages initially shipped a generic shell with <title>plugreports</title> — telling Google every dynamic page was a duplicate of the homepage. The fix was a shared _seo.js helper that strips the shell's head and injects per-item title, description, self-canonical, hreflang and OG tags at the edge, so crawlers need zero JS execution.

Machine translation via Workers AI. Nine languages × 400+ profiles would have taken months by hand. Instead, the profiles are translated in bulk through a tiny /api/translate endpoint wrapping @cf/meta/m2m100-1.2b (60 short strings per call, merged into the language packs at build time). Human review happens in the admin panel afterward — machine translation is the draft, not the final word.

Video from KV, with range streaming. Identification clips (kept under 3 MB so they load on any connection) are stored as binary KV values and served by a Pages Function that honors HTTP range requests — so HTML5 <video> scrubbing works with no R2 bucket and no video host. The homepage slider and /watch/ hub hydrate from a videos collection, so uploading a clip in the admin panel (with a "feature on homepage" checkbox) needs no rebuild.

What I'd do differently

  • Never batch concurrent edits to the same source file. I corrupted the generator mid-session that way (6× duplicated content, and Python's last-definition-wins masked it). Recovery was raw.githubusercontent.com + the last known-good commit. Keep your generated site in git and push often.
  • Cache-bust every asset pin. Cloudflare's edge caches /assets/* hard. Every JS/CSS change bumps a ?v= pin and the service-worker cache name together, or you're debugging a week-old stylesheet.
  • Media in KV is fine — with short cache lifetimes. Re-uploads reuse the same filename, so max-age=3600, must-revalidate instead of immutable year-long caching.

Why it matters

The traffic pattern that convinced me this was worth building: search-console data showed huge query volume around identification ("what does X look like"), mixing dangers, and quitting timelines — questions where a wrong answer can kill someone. If the site helps one person recognize an overdose sign at 3 a.m., the whole stack was worth it.

The project is live at plugreports.com — the drug library, mixing dangers, hotline directory and video library are the best starting points. Feedback and corrections are welcome via the suggestion box.

plugreports is an independent harm-reduction project. It compiles public NIDA, DEA, EMCDDA/EUDA, WHO and CDC data for education and overdose prevention — not medical or legal advice.

📰 Read the original article on Dev.to AI

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