What We Built

Reddit moderators have one tool for handling their queue: scroll down and work through it in order. Spam, self-harm posts, harassment campaigns, and wrong-flair reposts all land in the same flat list with no signal about which one needs immediate attention. We saw a research study documenting exactly this problem and realized the fix was straightforward in concept and had never been built. That became Triage.

How We Built It

We built Triage on Devvit's new WebView system using a Preact frontend, an Express API layer, and Redis for caching the scored queue between refreshes. Every item that enters the queue passes through a two-layer classification pipeline. A rule-based scorer handles known patterns instantly using keyword matching across urgency tiers. A Gemini 2.5 Flash shadow scorer then runs over the same items to catch edge cases the rules miss, flagging posts where the language signals harm even if no explicit keyword matched. When the AI disagrees with the rule-based tier at 85% confidence or higher, it promotes the item. That threshold took significant tuning to get right: too low and routine posts get falsely elevated, too high and the AI's judgment never gets used.

Challenges We Faced

The hardest challenge was the Devvit platform itself. The settings API for storing the Gemini key fails silently in ways that are invisible until runtime. The WebView sandbox has bridge constraints that required workarounds we had to discover through trial and error. Custom post types were deprecated mid-development. None of this is documented clearly. We shipped anyway by building a local threat-floor fallback so the tool works fully on rule-based scoring if the AI layer is unavailable, meaning the app degrades gracefully rather than breaking.

What We Learned

What we learned is that accurate severity classification at scale requires two things: a fast deterministic layer for known patterns and an independent AI layer that is not biased by your existing rules. We intentionally kept the two systems separate so Gemini scores independently rather than just confirming what the keyword matcher already decided.

Built With

Share this project:

Updates