-
-
A Conclave decision room: the team votes, quorum auto-applies the outcome, and Decision DNA shows 100% past agreement to REMOVE.
-
The Living Rulebook: your team's decision history at a glance, with impact stats, 14-day activity, the outcome mix, and a phrase tester.
-
Simple, mod-configurable settings: auto-routing, scheduled sweeps, human-only bans, and an optional semantic toggle.
-
One click on any post shows its Decision DNA: the team's dominant outcome and how consistently they've ruled before.
-
Weekly calibration digest in modmail: shows new mods where they agreed with, and diverged from, the team.
Project Story: About the project
Inspiration
Reddit's modqueue treats every moderator as a lone agent clearing an inbox. But the hardest part of moderating isn't volume; it's the isolation of the borderline decision (the 2 a.m. "is this over the line?" call you make alone), the inconsistency that creeps in across a distributed team, and the institutional knowledge that walks out the door when a veteran mod leaves. The CHI 2026 study of how mods use the modqueue put numbers to it: 84% of mods leave the queue to gather context, and teams constantly collide and re-litigate the same calls. I wanted to build the thing that's missing: not a faster inbox, but a memory for the team.
What it does
Memex is institutional memory for moderation. One app:
- Decision DNA: on any post or comment, Memex shows how your team has ruled on similar content before: the dominant outcome, a consistency score, and the closest past decisions with the reasons mods gave. It works across post types (text, image, poll, and link posts, where the domain is folded in so repeat spam/affiliate domains are recognized). Low consistency is itself a signal: it flags genuinely borderline content that deserves a team decision. You can pull it up instantly from the mod menu on any item, or see it live inside a Conclave, or paste any phrase into the Rulebook's "test a phrase" tool.
- Conclave: borderline items become mod-only async decision rooms. Mods vote Remove / Keep / Warn / Escalate; when quorum is reached the consensus action auto-executes for reversible actions. Bans never auto-execute: they're surfaced for a human click (per Reddit's 2026 admin policy). Votes and presence update live.
- Living Rulebook: a custom post showing the team's applied rules, with live impact stats (total decisions, this week, open conclaves), a proportional outcome bar, a 14-day sparkline, the open conclaves, and recent precedents.
- Calibration: new mods cast shadow votes that don't count toward quorum; a weekly digest (or one sent on demand) shows where they diverged from team consensus, so they learn the team's standards in weeks instead of months.
- Consistency Sweep: on demand or on a schedule, Memex audits recent live posts and flags ones similar to content the team has REMOVED before but that are still up, using the team's own past decisions as the baseline. Flagged items are reported into the modqueue (never auto-removed), with a modmail summary.
Plus: Memex learns from every native mod action (each manual remove/approve becomes a precedent), writes native Reddit mod-notes on every team decision, and supports keyword/account-age auto-routing.
How I built it
Built on Devvit Web (Reddit's new Developer Platform): a React 19 + Tailwind
webview over a Hono server, with state in per-subreddit Redis. A single
custom-post type renders an inline splash card in the feed and an expanded webview;
the server classifies each post (Conclave vs Living Rulebook) and returns the right
snapshot. The "Decision DNA" engine is local by default (trigram + token
Jaccard similarity, batched with Redis mGet), so it runs with no external API, no
key, and no per-comment cost. The new server runtime also let me add an optional,
opt-in semantic layer: paste an embedding API key and Memex auto-detects the
provider from its shape (OpenAI or Google Gemini), blends embedding cosine on top
of the local score, and caches vectors in Redis. It is off by default and never
calls out without a recognized key, so the app stays error-free out of the box.
50 automated tests run the real similarity, Decision DNA retrieval, vote/quorum,
auto-route, sweep, and provider-detection logic against an in-memory Redis.
Challenges I ran into
The big one: I built Memex on Devvit Blocks, then migrated the entire app to Devvit
Web days before the deadline to stay compliant. While testing, I learned from
r/Devvit and the Devvit Discord that the Blocks custom-post renderer is being
retired (custom posts disabled June 30, 2026, and new Blocks custom-post apps no
longer approved). Rather than ship something that would stop working, I rebuilt the
whole front end on Devvit Web and re-platformed the server, porting the entire
decision engine intact, so Memex stays compliant and keeps working past the Blocks
sunset. I kept the original Blocks build on a separate blocks-backup branch for
reference. The migration surfaced a string of
real, hard-won gotchas on the new platform:
- Data-access model flip. Blocks passed
context.redis/context.redditinto every function; Devvit Web exposes module-levelredis/reddit/contextfrom@devvit/web/server. Every persistence and Reddit-API call had to be reworked. reddit.getCurrentSubredditName()doesn't exist on Web (it's only in a doc example). The current subreddit comes fromcontext.subredditName/context.subredditId. Found by reading the shipped type defs, not the prose docs.- Branded Thing-IDs.
getPostById/getCommentByIdnow require`t3_${string}`/`t1_${string}`template-literal types; stored string IDs needed theT3()/T1()helpers. - Form-data round-trip. A menu action and its form submit are separate requests,
so I park the half-built routing input in Redis keyed by the moderator and reclaim
it on submit, which survives regardless of how the platform threads form
data. - Settings schema. Web settings live under
settings.global/settings.subredditindevvit.json(not afieldsarray), and secrets areisSecretglobal strings. - Strictness. The Web template enables
noUncheckedIndexedAccessandexactOptionalPropertyTypes, which caught several latent index/optional bugs in the port.
I validated the final devvit.json against Devvit's own bundled config parser, and
got type-check, ESLint, the Vite build, and all 50 tests green.
Accomplishments that I'm proud of
- A genuinely net-new capability for the Devvit ecosystem: no other mod tool surfaces how the team decided on similar content at decision time, scores consistency, or calibrates new mods against the team's real pattern.
- Re-platformed an entire app to Devvit Web under deadline without losing a feature, and used the move to add an optional, vendor-agnostic semantic layer (paste any supported key, provider auto-detected).
- Local-first and private by default: works the instant it's installed, with the semantic layer strictly opt-in, never calling out without a recognized key, and documented in a privacy policy.
What I learned
The bottleneck in moderation isn't reading speed; it's decision legitimacy and team coherence. Reframing from "make one mod faster" to "give the team a memory" produced a tool mods actually want. And building on a platform mid-transition taught me to trust the shipped type definitions over the prose docs, and to design every external dependency so the app degrades gracefully without it.
What's next for Memex
- Extend the semantic layer (it already auto-detects OpenAI and Gemini keys): more providers, per-subreddit keys, and batched embedding of the backfill corpus.
- Team-level analytics: time-to-decision, agreement trends, drift detection.
- Per-language tuning of the local engine.
- Pilots with mid-size subreddits to publish real impact numbers.
Built With
- devvit-web-(reddit-developer-platform)
- gemini
- hono
- node.js
- openai
- react-19
- redis
- tailwind-css
- typescript
- vite
- vitest

Log in or sign up for Devpost to join the conversation.