Inspiration

Every moderator has experienced it: you're reviewing a post, the username looks familiar, but you
can't remember why. Was this the person who apologized after a warning last month? Or the one who
keeps testing the rules? You check modmail—nothing recent. You scan mod logs—too much noise. The moment passes, and you make a decision without the full picture.

ModSync was born from this frustration.

Reddit's native mod tools are powerful for individual actions but weak on institutional memory. Mod notes exist but are buried. Context is scattered across logs, modmail, and tribal knowledge that
lives only in moderators' heads. When mod teams change—and they always do—that knowledge walks out
the door.

We realized that what moderators needed wasn't another punishment tool. They needed a collaborative memory system—a shared brain that remembers every interaction, surfaces relevant context at the
moment of decision, and keeps the entire team synchronized.

What it does

Building ModSync taught us that the best tools are invisible until you need them.

We learned that Devvit's platform is remarkably capable but requires thinking differently about data persistence. The Redis implementation has intentional constraints (no list operations like
lPush/lRange) that pushed us toward cleaner architectural patterns using hashes with
application-layer sorting.

We discovered that context is king for moderators. Raw numbers (15 removals, 2 approvals) tell a
story, but the why behind those numbers matters more. A user with 15 removals who's genuinely trying to improve deserves different treatment than one who's actively hostile. That's why team notes
became the heart of ModSync.

We also learned that demo-ability matters. Building features that work is one thing; building
features that show well in 60 seconds required us to think carefully about information hierarchy and progressive disclosure.

How we built it

odSync is built on Devvit's web-based architecture, using:

  • TypeScript end-to-end for type safety across client and server
  • React for the dossier interface with a tab-based progressive disclosure pattern
  • Hono as a lightweight, fast server framework for API routing
  • Devvit Redis for persistent storage with tenant isolation per subreddit

The architecture follows a clear separation:

┌─────────────────────────────────────────────────────────┐
│ Client (React) │
│ └── DossierGame.tsx - Tabbed UI with Overview/Notes │
├─────────────────────────────────────────────────────────┤
│ Server (Hono) │
│ ├── /api/dossier/* - Dossier data & actions │
│ ├── /internal/menu/* - Context menu handlers │
│ └── /internal/triggers/* - Post/comment listeners │
├─────────────────────────────────────────────────────────┤
│ Storage (Redis) │
│ ├── modsync:sub:{id}:user:{id}:meta - User metrics │
│ ├── modsync:sub:{id}:user:{id}:notes - Team notes │
│ └── modsync:sub:{id}:watchlist - Active monitoring │
└─────────────────────────────────────────────────────────┘

Key design decisions:

  • Subreddit-scoped data: All data is isolated per subreddit, so user reputation in r/gaming doesn't affect r/science
  • Hash-based note storage: Notes stored as {noteId: JSON} in Redis hashes, sorted by timestamp in
    application code
  • Pending context pattern: Menu clicks store context in Redis with TTL, then navigate to the ModSync post where the UI reads and clears that context

Challenges we ran into

Challenge 1: Redis List Operations Don't Exist

Our initial design used Redis lists (lPush/lRange) for note storage—a standard pattern. We
discovered mid-development that Devvit's Redis implementation doesn't support these operations.

Solution: Pivoted to hash-based storage where each note is a key-value pair (noteId → JSON). Sorting happens in application code. This actually resulted in cleaner code with better random-access
capabilities.

Challenge 2: Custom Post Navigation

Devvit's navigateTo for custom posts only accepts full URLs, not relative paths to entrypoints. Our initial approach of navigating to /dossier-game.html failed silently.

Solution: Created a "ModSync Post" per subreddit that serves as the dashboard home. Menu actions
store pending context in Redis, navigate to the known post URL, and the post's splash screen reads
that context to display the appropriate dossier.

Challenge 3: Making Context Instantly Scannable

Moderators often have seconds to make decisions. Showing all data overwhelmed; showing too little
was useless.

Solution: The tabbed interface with a glanceable status badge and metrics grid. The badge color
(green/yellow/orange/red) communicates risk level instantly. Details are one click away but never in the way.

Built With

Share this project:

Updates