← Back to the Arsenal
Full-stack · SSR · Auth · 2026

MUSE Students Voice

An anonymous-but-accountable grievance channel for a university, where a complaint only becomes official once enough peers back it.

1,159
verified student IDs
0
identities exposed to client
SSR
edge-rendered
MUSE Students Voice screenshot 1MUSE Students Voice screenshot 2MUSE Students Voice screenshot 3

The problem

Students at MUSE had no safe way to raise campus issues. Named complaints invited retaliation; fully anonymous forms invited spam and were ignored by the administration because nobody could vouch that the sender was even a student.

Constraints

  • A complaint must be provably from an enrolled student, without ever showing who wrote it.
  • No moderator, no budget — the escalation rule has to be mechanical, not human.
  • Runs on a free edge tier: no long-lived server, no background workers.

What I built

  • USN (roll number) verification against a seeded roster of 1,159 enrolled IDs before an account can post.
  • Postgres row-level security plus security-definer RPCs: the author column is never selectable by the client — only the RPC can join it, and it never returns it.
  • Peer voting with a threshold; crossing it flips the complaint to 'escalated' and renders a formal PDF letter addressed to the department.
  • Server-side rendering on Cloudflare Workers so complaint pages load instantly on campus Wi-Fi.

Trade-offs

RLS + security-definer RPCs instead of a custom API layer

One place to reason about who can read what. A leaky endpoint can't bypass the database itself — the guarantee lives below the app.

Threshold voting instead of moderators

No volunteer moderator would survive exam season. A rule that runs itself keeps the system alive when nobody is watching.

Roster seeding over email OTP

Institutional email delivery was unreliable; the roster was already authoritative and offline-verifiable.

Outcome

  • Anonymous posting with zero client-side access to author identity.
  • Complaints escalate into a printable, formally worded PDF with no manual step.
  • Taught me that access control is a data-model problem, not a UI problem.

Stack

TanStack StartReact 19Supabase (Postgres, RLS)Cloudflare WorkersTypeScript
Want the long version?

Happy to walk through the decisions live.

Email me →