Skip to content
karim.semaan(open to work)
WorkExperienceAboutSkillsContactResume ↓
← All work
Birthday Buddy preview
Generative AIProtected2026

Birthday Buddy

AI WhatsApp birthday concierge

A working private build, not a mockup: a real WhatsApp Business number receives and processes live messages, contacts import via Google OAuth with two-stage relationship tagging, and the latest structured security review passed 18 of 18 checks.

Upcoming reminders · 6 contactsSynthetic preview · invented contacts

Runs in your browser on synthetic contacts. The birth year is ignored; the relationship sets the illustrative heads-up lead time.

  1. 1JadfriendJun 11heads-up 3d beforetoday
  2. 2Teta RanafamilyJun 14heads-up 7d beforein 3 days
  3. 3OmarfriendJun 23heads-up 3d beforein 12 days
  4. 4MayafamilyJul 2heads-up 7d beforein 21 days
  5. 5LucascolleagueSep 18heads-up 1d beforein 99 days
  6. 6SofiafriendJan 5heads-up 3d beforein 208 days

Synthetic preview. Invented contacts; no real users, messages, or product code. Days away are counted from a fixed reference date, Jun 11, 2026, so the list is deterministic. The real product imports Google contacts, infers each relationship with Claude, and sends the reminder over WhatsApp.

Synthetic preview with invented contacts. No real users, messages, or product code; days away count from a fixed Jun 11, 2026 reference date.

Protected work

A private SaaS build, so source, WhatsApp Business wiring, and user data are not public. Happy to demo it on synthetic contacts.

Request access

Birthday Buddy is a WhatsApp chatbot SaaS that makes sure you never miss a birthday: contacts arrive via Google OAuth or a parsed WhatsApp chat export, every contact gets a relationship and closeness tag, and an hourly reminder engine messages you before each date with a drafted greeting. Relationship inference runs in two stages: a deterministic rule stack that reads Google's relations field, groups, starred status, and kinship words across seven languages (English, transliterated Arabic, Spanish, French, Italian, German, Hindi), then a batched Claude Sonnet pass for whatever the rules cannot decide. In conversation, Claude Haiku classifies inbound intents and Sonnet drafts the messages, with prompt caching and reviewed prompt-injection mitigations. Everything runs on Supabase Edge Functions (Deno/TypeScript) over Postgres with RLS: two pg_cron engines (birthday reminders with a dedup ledger and snooze handling; nudges with a 9am-9pm local-time window and lifetime caps), HMAC-verified WhatsApp webhooks, and signed time-limited URLs for the contact review page. Successive structured security reviews hardened the build; the latest passed 18 of 18 checks.

  • TypeScript
  • Deno
  • Supabase Edge Functions
  • PostgreSQL
  • Claude (Haiku + Sonnet)
  • WhatsApp Business API
  • Google OAuth

Architecture · contacts → drafted WhatsApp greetings

  1. 01

    Contact import

    Contacts import via Google OAuth, or from a parsed WhatsApp chat export, into a Postgres schema with row-level security.

  2. 02

    Relationship inference

    A two-stage engine (a deterministic multilingual rule stack, then a batched Claude Sonnet pass) tags each contact's relationship and closeness.

  3. 03

    pg_cron reminders

    Hourly pg_cron engines fire birthday reminders (dedup ledger + snooze) and nudges (9am-9pm local window, lifetime caps).

  4. 04

    Intent + drafting

    Claude Haiku classifies inbound intents; Claude Sonnet drafts each greeting, with prompt caching and reviewed prompt-injection mitigations.

  5. 05

    WhatsApp delivery

    Sent via the WhatsApp Business Cloud API over HMAC-verified webhooks, all on Supabase Edge Functions (Deno).

Function code
10,781 LOC TS
AI
Claude Haiku + Sonnet
Kinship languages
7+
Security review
18 pass / 0 fail

What I'd improve

Two things are next. Meta still gates this WhatsApp Business account from sending native Flows until business verification clears, so contact review lives on an HMAC-signed web page instead of in-chat cards; clearing verification unlocks the in-chat flow. And the voice layer is plumbing ahead of product: the generator already injects a per-user voice fingerprint into every draft, but the capture and distillation flow that populates it is still a designed spec, so landing it is the difference between a generic greeting and one that actually sounds like you.

Private · request access
Want something like this? Get in touch →

Measured:30/30 chatbot evals·20-case Bastion eval·Serving·Calibration Lab

© 2026 Karim SemaanBuilt with Next.js, Tailwind & Supabase.LinkedIn ↗︎GitHub ↗︎