← back to work

Founder & Full-Stack Developer

ClubsForKids

A full-stack web & mobile platform built to replace a school's paper-based after-school club lottery, designed for 500+ families.

PythonFastAPIReactReact NativePostgreSQLJWT AuthFirebase

500+ families

Built to support

30 hrs → 1 click

Lottery setup time

3

User roles

Problem

Plantation Park Elementary ran its after-school enrichment club enrollment entirely on paper: a manual lottery process for 500+ families, with no digital system for registration, fair assignment, attendance tracking, or parent-teacher communication. Setting up a single lottery run took a coordinator roughly 30 hours of manual work.

Approach

Designed and built a decoupled FastAPI + React application from scratch, with real-world business logic rather than basic CRUD: a fairness-aware lottery algorithm that processes siblings together across rounds and manages simultaneous waitlists, a three-role permission system (parent, teacher, coordinator) enforced server-side through actual parent-student-teacher relationship checks rather than simple role flags, and a generalized messaging system built on a single threads/participants data model that scales from 1:1 conversations to school-wide announcements. Security was treated as a first-class concern: bcrypt password hashing, JWT auth, login rate-limiting, environment-based secret management, and a deliberate security review pass that caught and removed a leftover development endpoint capable of wiping the database.

Outcome

Cut lottery setup time from roughly 30 hours of manual work to a single click, while correctly handling sibling fairness and multi-round waitlist promotion. The platform is built to support 500+ families with role-based dashboards for parents, teachers, and the school coordinator, replacing manual attendance tracking, enrollment paperwork, and approval workflows. It's currently in discussions with the school for adoption through the district's approval process, with a sponsorship-based monetization model in development.

See it in action

Short walkthroughs of each role’s dashboard.

Coordinator

Teacher

Parent

A few of the harder engineering problems solved

  • Fair sibling lottery logic. Siblings are processed together in rounds: every sibling tries their first choice before anyone moves to their second, so a family isn’t split apart by pure chance. This surfaced a real database transaction bug: assignments had to be committed individually inside the loop rather than batched at the end, otherwise later iterations read stale enrollment counts and could over-fill a club past capacity.
  • Relationship-based authorization, not just role checks. A parent can only message their own child’s actual assigned teacher, verified by tracing parent to family to student to club assignment to teacher, not a simple “is this a parent” check. Coordinators can also revoke a specific parent’s access to a specific child (without deleting their account) to handle real-world custody or safety situations.
  • A FastAPI route-ordering bug where a wildcard route like /users/{user_id} was silently swallowing requests meant for a more specific route defined after it, a good reminder that route declaration order matters.
  • A React focus-loss bug caused by defining a component with a <textarea> inside another component’s function body, so it was recreated (and the input remounted) on every parent re-render.