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

  1. Attendees join an event via a unique HUSKY-KEY
  2. If they opt out, they take a quick selfie (reference image)
  3. The selfie is stored as a Base64 string in SQLite
  4. Organizers upload event photos
  5. AI matches faces in photos against opt-out selfies
  6. 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.

Share this project:

Updates