Skip to content
Back to all work
Application

Secret Santa

Gift-exchange draws where even the organiser does not know the result.

Year
2026
Status
Live
Role
Solo: back end, front end, security.
Secret Santa

The organiser types in the participants, the app draws the pairs and gives each person their own signed link. Only the owner of a link sees what is behind it: the organiser, even when taking part, sees only who has looked already. No accounts for participants, no email addresses collected.

Stack

  • Python
  • Flask 3
  • SQLAlchemy 2
  • itsdangerous
  • pytest
  • Vanilla JS
  • REST APIs

In practice

  • Nobody draws themselves, and no two people draw each other: a shuffled cycle when there are no restrictions, and a solver with a hard step limit when couples have to be kept apart.
  • A link that cannot be forged or reused by somebody it was not meant for: each one is signed, and the part that identifies you rides in the piece of the address a browser never sends to the server, so it stays out of the logs.
  • The organiser can see who has already looked and nothing else, which is checked by a test that fails if a pair ever appears in that response.
  • An optional account that grants no extra sight: it remembers your events, and that is all it does.
  • Works on the cheapest hosting there is: no build step, no Node, and the same code runs on SQLite at home and MySQL in production.

How it is built

  • A REST API kept clear of the static front end: 15 endpoints, 81 tests under pytest.
  • Draw: a Hamiltonian cycle in linear time with no exclusions, backtracking with an MRV heuristic and a step ceiling when there are, seeded from a CSPRNG.
  • Tokens signed with HMAC over a separate salt, carrying a one-time component from the database so a single link can be revoked.
  • Sessions with CSRF protection scoped to cookie-authenticated requests only, and a password reset with no token table: the payload holds a fingerprint of the current hash, so changing the password spends the link.
  • SQLAlchemy throughout, so SQLite locally and MySQL or PostgreSQL in production without touching the code.

Organiser

Participant

Dark mode

Let's build something together

Got something in mind? Even half an idea is enough to start a conversation. Every message gets an answer, even when the honest answer is that someone else suits it better.

An answer within 24 hours, with a first estimate and how I would approach it.

Based in Belgium, working remotely with clients in English and Polish.