Anonify: Privacy-First Event Photo Redaction
💡 Inspiration
We’ve all been there: you attend a wedding, a tech conference, or a party, and suddenly your face is in a hundred photos shared on a public Google Drive or social gallery. For many, this is a privacy nightmare.
We wanted to build a tool that gives power back to the attendee without making the organizer’s life impossible. Anonify was born from the idea that “opt-out” should actually mean something in the digital age.
🛠️ How We Built It
We built Anonify as a multi-layered, local-first system to ensure maximum privacy:
- Frontend: Next.js with TypeScript and Tailwind CSS for a sleek, responsive organizer dashboard and a simple, mobile-friendly attendee “Opt-Out” portal
- Auth: Clerk for secure organizer authentication
- Backend: Flask API managing relational data with SQLite (portable, self-contained database)
- AI / Vision: Python microservice using OpenCV and face recognition
- AI Usage: Claude, Codex, Gemini
The Flow
- Attendees join an event via a unique HUSKY-KEY
- If they opt out, they take a quick selfie (reference image)
- The selfie is stored as a Base64 string in SQLite
- Organizers upload event photos
- AI matches faces in photos against opt-out selfies
- Organizer reviews detections and clicks “Anonymize” to apply persistent blurs
🧠 What We Learned
We learned that handling facial recognition requires a careful balance between user experience and privacy.
A major focus was confidence scoring—instead of making risky assumptions, the system flags uncertain matches for manual review.
We also learned how to effectively coordinate a Next.js frontend with a Python AI backend in near real-time.
🚀 Challenges We Faced
🔐 The “Turnstile” Trouble
Cloudflare Turnstile bot detection interfered with our local Clerk authentication flow. We had to debug middleware and browser security headers to stabilize development.
📐 Coordinate Math
Mapping pixel-based face detection to responsive frontend overlays required non-trivial geometry:
$$ \text{RelativePos} = \frac{\text{PixelPos}}{\text{ImageDimension}} \times 100 $$
🧩 Persistent Redaction
Ensuring anonymized images stayed redacted across reloads required tight synchronization between:
- Next.js state
- Flask backend
- SQLite status updates
🎯 Final Thought
A picture is worth a thousand words—and with Anonify, you get to choose which stories yours tells.



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