birthday-ping

Next.js
MongoDB
Resend
GitHub Actions
TypeScript
NextAuth
React Email
Zod

birthday-ping is a full-stack birthday reminder app built with Next.js App Router, MongoDB, and Resend. It sends automated daily email digests triggered by a GitHub Actions cron job, supports Google OAuth via NextAuth, and lets users import and export birthdays as standard .ics calendar files compatible with Apple Calendar and Google Calendar.

Source Code & Demo

Key Features

  • Automated email digests via Resend
  • Google OAuth authentication
  • Calendar import/export
  • Daily email digests triggered by GitHub Actions cron
  • ICS calendar import with confidence scoring

Code Highlights & Design Choices

Calendar apps export events in wildly inconsistent formats. Rather than requiring a specific structure, the importer assigns a weighted score across multiple signals — recurrence rules, category tags, summary keywords, and a known UID prefix — and maps the total to a confidence level. Users see a clear high/medium/low indicator instead of a binary pass/fail.

The daily email job needs to send one digest per user, not one email per birthday. A single aggregation pipeline groups all subscriptions by userId, joins both the birthday and user documents in one pass, and returns the full payload ready for Resend. This avoids N+1 queries and keeps the email-sending loop simple.

Challenges & Solutions

Calendar files exported from different apps (Apple Calendar, Google Calendar, Outlook) use inconsistent formats for birthday events — some omit recurrence rules, others use non-standard category labels.

Built a multi-signal confidence scoring system that weighs recurrence frequency, category tags, summary keywords, and UID prefixes independently. Ambiguous imports surface a warning rather than silently failing, and users see a confidence badge so they can review low-confidence entries before saving.

Birthday emails need to go out daily on a schedule, but serverless platforms don't offer a free built-in cron trigger, and adding an external service increases operational complexity.

Used a GitHub Actions scheduled workflow (cron: '0 9 * * *') to POST to a secured internal API route. The endpoint validates a shared secret header before processing, keeping the infrastructure free and entirely within the existing GitHub repo.

Outcomes & Impact

birthday-ping is actively used — it's replaced the manual birthday-checking habit. The calendar round-trip (import from Apple Calendar, export back) works without data loss, and the confidence scoring has caught several ambiguously formatted events that a naive parser would have silently dropped.

What I Learned

This project deepened my understanding of the iCalendar spec (RFC 5545) and how loosely calendar apps actually follow it. I learned to write MongoDB aggregation pipelines for multi-collection joins, use React Email to render transactional emails server-side, and wire up GitHub Actions as a zero-cost cron trigger for a deployed Next.js app.