Qrum home page

Qrum

A volunteer management platform that simplifies event coordination for organizations. Staff create, manage and track events while volunteers browse opportunities, sign up and check in - all while allowing public access and .

Next.js / TypeScript / Supabase / PostgreSQL / PostGIS / Elasticsearch / Kafka / Redis / Grafana / Prometheus / Loki / Alloy

VISIT WEBSITE

Project Background

Qrum began as a senior capstone project for a non-profit organization that required a volunteer management system. However, it soon became clear that there was a wider need. Volunteer coordinators juggling spreadsheets, group chats and paper sign-in sheets to manage events and old fossilized user interfaces hiding behind paywalls. I wanted to build a system that handled the full event creation lifecycle and coupled it with the kind of reliability and polish you'd expect from a production application, totally free of charge.

The frontend is built with Next.js and TypeScript, styled with a custom glassmorphism design system that uses layered blur, transparency and subtle gradients to create depth. The backend runs on self-hosted Supabase, a PostgreSQL database, that enables custom RPC functions and row-level security policies that enforce role-based access at the database layer as well as on the server.

Role-based access control separates staff and volunteer permissions. Staff can create events with capacity limits, set dates and locations, and archive past events. Volunteers browse available events, register, and check in. Every mutation — status changes, edits, sign-ups — is recorded in an event change log, giving coordinators a full audit trail.

Technical Highlights

Location-based event search was one of the more interesting problems to solve. Addresses entered by staff are geocoded to latitude/longitude and stored as PostGIS geography points. The nearby events RPC uses ST_DWithin for fast radius queries, returning results sorted by distance. This lets volunteers find events near them without knowing exact addresses.

Full-text search is powered by Elasticsearch, kept in sync with the PostgreSQL primary through change data capture via Kafka. This decoupled architecture means search stays fast and up-to-date without adding load to the main database during writes.

To protect the API, I used a traditional double sliding window rate limiter using Redis. The two windows — a short burst window and a longer sustained window — prevent both rapid-fire abuse and slower sustained attacks while keeping the experience smooth for legitimate users.

Observability is handled by a Grafana stack. Alloy runs as a lightweight collector on the host, scraping Prometheus metrics from the application and shipping structured logs to Loki. Pre-built dashboards surface request latency, error rates and resource usage, while log queries in Grafana make it possible to trace a single request across services without SSH-ing into a box.

Static Previews

Qrum volunteer profile dashboard Qrum event detail view