Inspiration

Mod teams on large subreddits often have no structured way to hand off context between shifts. The incoming mod has to piece together what happened from scattered modmail threads and removed posts. I wanted to fix that, one pinned post that shows the community's current health and the last mod's notes.

What I built

ModPulse is a pinned dashboard post that gives mod teams two things:

  1. Live pulse indicator — CALM / ELEVATED / HEATED, calculated from reports and removals over the last 2 hours, auto-updated every 10 minutes via a scheduler job.
  2. Shift tracking + handoff log — mods start a named shift, log urgency-tagged notes mid-shift, and end with a structured handoff. The next mod sees it the moment they open the dashboard.

When the community tips into HEATED, ModPulse automatically fires a modmail alert so offline mods know to check the queue.

How I built it

Built entirely on Devvit using:

  • Custom Post Type (Blocks UI) for the interactive dashboard
  • Redis for shift state, notes, pulse data, and handoff history
  • Scheduler (10-min cron) for pulse recalculation
  • Triggers on PostReport, CommentReport, and ModAction for real-time event counting
  • Modmail API for heated-community alerts

The trickiest part was the form system. Devvit's useForm hook registers form keys during the render phase — calling ui.showForm() from inside an onPress handler fails because the hook context is gone by then. The fix: buttons set a pendingForm state value, and the next render detects it and calls ui.showForm() while hooks are still registered. Took deep source-level debugging to figure out.

I also hit a "Exceeded maximum iterations of 128" error from running three separate useAsync hooks in parallel. Solved by collapsing them into one useAsync with a single Promise.all.

What I learned

  • Devvit's render/hook lifecycle is strict — hooks must register in the same render pass where they're used.
  • Redis key design matters early; easy to paint yourself into a corner with flat keys.
  • devvit playtest is essential — devvit upload doesn't hot-reload existing installed posts.

Built with

  • Devvit (v0.12.24)
  • TypeScript
  • Reddit Blocks (Custom Post Type)
  • Redis (via Devvit)
  • Devvit Scheduler
  • Devvit Triggers (PostReport, CommentReport, ModAction, AppInstall)
  • Reddit Modmail API

Built With

Share this project:

Updates