Inspiration

Proxy attendance is an open secret on most college campuses. Static QR codes get screenshotted and shared in WhatsApp groups within seconds, sign-in sheets get passed around, and professors are left with attendance data they don't fully trust. As a student who has watched this play out firsthand, I wanted to build something that actually closes these loopholes instead of just digitizing the same broken paper process. QRotation started from one simple question: what if the QR code itself expired before anyone could screenshot and forward it?

What it does

QRotation is a privacy-first attendance platform for colleges. Professors start a class session and the app displays a QR code that rotates every few seconds, each one a fresh, server-signed, HMAC-secured token tied to that exact session. Students scan the live code from the QRotation PWA, and the backend runs every scan through a verification pipeline that checks token validity, device binding, IP behaviour , and geofencing before it ever gets marked present. Every attendance record comes with an explainable presence score, so nobody is stuck trusting a black box - professors can see exactly why a scan was accepted or flagged. Suspicious scans get routed into a fraud review queue instead of being silently rejected or silently accepted, and students have a proper appeals workflow if a genuine attendance gets flagged by mistake. Admins get institution-level oversight across departments, courses and sessions.

How I built it

The backend is Flask with SQLAlchemy, structured around a data model that covers users, courses, class instances, sessions, QR tokens, attendance records, presence verification, fraud alerts and appeals. Tokens are generated with a nonce, timestamp and expiry, signed with HMAC, and stored as hashes only - so even the database never holds a usable raw token. Flask-SocketIO pushes attendance updates to the professor's dashboard in real time as students scan in, so a session fills up live instead of needing a manual refresh. The frontend is server-rendered with Jinja2 and Tailwind, and the scanner page is a full PWA with a service worker, so students can scan even with a flaky connection - the payload gets sealed locally and synced once the network is back. Role-based blueprints separate the student, professor, admin and API surfaces cleanly, which made it much easier to reason about who can see and do what.

Challenges I ran into

Getting the token rotation window right took a lot of tuning - too short and genuine students get rejected because of network lag, too long and it defeats the whole purpose of rotating in the first place. I ended up building in a small configurable grace period to absorb latency without reopening the replay window. Making the fraud signals explainable rather than a single opaque "fraud/not fraud" flag was another real challenge, since professors needed to trust and act on the output rather than just accept whatever the system decided. Building reliable offline support for the scanner - encrypting and queuing scan payloads client-side, then syncing safely without creating duplicate attendance records - also took several iterations before it held up under flaky campus WiFi.

What I learned

I came out of this with a much deeper understanding of how to design short-lived, cryptographically signed tokens correctly, and how something as small as server clock drift can quietly break an entire verification pipeline. I also learned that building for trust matters as much as building for security - a system that silently rejects people breeds resentment, while one that explains its reasoning and offers a review path gets adopted willingly. Working with Flask-SocketIO at this scale also taught me a lot about keeping realtime state consistent across multiple workers.

What's next for QRotation

Next up is a proper OpenAPI spec for the HTTP API so QRotation can plug into existing campus ERPs, a Docker Compose setup with Postgres and Redis for production-grade deployments, and native mobile scanner apps to complement the PWA. I'd also like to add richer analytics for professors - attendance trends per student, per course, and early warning flags for students falling below attendance thresholds.

Built With

Share this project:

Updates