A multi-channel notification system for tracking personal events with timezone support, calendar sync, and automated reminders.
Live at: your-domain.com
See DATABASE_SCHEMA.md for detailed Firestore schemas, JSON payloads, and worker message flows.
| Component | Path | Stack | Deployment |
|---|---|---|---|
| Frontend | ui/ |
Next.js 16, Tailwind CSS, shadcn/ui, Firebase | Vercel |
| Workers | python-workers/ |
Python, Redis, Docker | Docker VM |
| MCP Server | mcp-server/ |
Node.js, Firebase Admin | Local |
- Multi-Channel Reminders — Email (SMTP / Google Workspace), Telegram, Discord with age/duration info
- Queue-Based Email System — Verification and reminder emails processed asynchronously via Redis for reliability and scale
- Timezone Intelligence — Reminders dispatched relative to the event's timezone
- Calendar Sync — Dynamic
.icsfeeds for Apple/Google calendar subscriptions - Global Reminder Timing — 6 preset timing options (midnight, 15m before/after, 1h, 6h, 10h)
- Progressive Form — Conditional fields based on event type (Birthday, Anniversary, Custom)
- PWA Ready — Installable web app with offline support
cd ui
pnpm install
pnpm devcd python-workers
docker compose up -dNote: The scheduler requires
serviceAccountKey.jsonto connect to Firestore. If it is missing, the scheduler will start in mock mode and push dummy test payloads to Redis.
cd mcp-server
npm install
npm startSet these in your Vercel project settings:
| Variable | Required | Description |
|---|---|---|
NEXT_PUBLIC_FIREBASE_API_KEY |
✅ | Firebase Web API key |
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN |
✅ | e.g. your-project.firebaseapp.com |
NEXT_PUBLIC_FIREBASE_PROJECT_ID |
✅ | Firebase project ID |
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET |
✅ | e.g. your-project.appspot.com |
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID |
✅ | Firebase messaging sender ID |
NEXT_PUBLIC_FIREBASE_APP_ID |
✅ | Firebase app ID |
CRON_SECRET |
❌ | Bearer token for /api/cron/remind authorization |
PORTAL_URL |
❌ | Optional portal URL for notification links (default: https://your-domain.com/dashboard) |
Note: SMTP, Telegram, and Discord credentials are no longer needed on Vercel. Email and verification codes are now processed asynchronously by Docker workers, not by the Next.js API routes.
NEXT_PUBLIC_FIREBASE_API_KEY=your_api_key
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=your_auth_domain
NEXT_PUBLIC_FIREBASE_PROJECT_ID=your_project_id
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=your_storage_bucket
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=your_sender_id
NEXT_PUBLIC_FIREBASE_APP_ID=your_app_id
TELEGRAM_BOT_TOKEN=123456:ABC-DEF
CRON_SECRET=your_secret_hereNote: During local development, SMTP/email functionality requires the Python workers to be running. The Next.js frontend creates jobs in Firestore; the scheduler and email worker process them asynchronously.
| Variable | Required | Used By |
|---|---|---|
REDIS_HOST |
✅ | All workers |
FIREBASE_CREDENTIALS |
✅ | Scheduler (path to serviceAccountKey.json) |
SMTP_HOST |
❌ | Email worker (default: smtp.gmail.com) |
SMTP_PORT |
❌ | Email worker (default: 587) |
SMTP_USER |
✅ | Email worker |
SMTP_PASSWORD |
✅ | Email worker |
SMTP_FROM |
❌ | Email worker (default: SMTP_USER) |
TELEGRAM_BOT_TOKEN |
✅ | Telegram worker |
| Variable | Required | Description |
|---|---|---|
FIREBASE_CREDENTIALS |
✅ | Path to serviceAccountKey.json |
cd ui
pnpm install
pnpm test # watch mode
pnpm test:coverage # single run with coverage45 tests across library utilities and components.
On every push/PR to main:
- Vitest unit/component tests with coverage
- Production build verification
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read, write: if request.auth != null && request.auth.uid == userId;
}
match /birthdays/{birthdayId} {
allow read, write: if request.auth != null && request.auth.uid == resource.data.userId;
allow create: if request.auth != null && request.auth.uid == request.resource.data.userId;
}
match /email_jobs/{jobId} {
allow read: if request.auth != null && request.auth.uid == resource.data.userId;
allow create: if request.auth != null && request.auth.uid == request.resource.data.userId;
allow update: if request.auth != null && request.auth.uid == resource.data.userId &&
only(['status', 'verifiedAt'].hasAny(request.resource.data.diff(resource.data).affectedKeys()));
}
}
}Note: Python workers use Firebase Admin SDK with service account credentials, so they bypass these rules for scheduler operations.
- Connect this repo to Vercel
- Set Root Directory to
ui - Framework preset: Next.js (auto-detected)
- Add all environment variables from the table above
- Deploy — Vercel handles build, CDN, SSL automatically
Add a Vercel Cron Job (in vercel.json or Vercel dashboard) to hit:
GET /api/cron/remind
Authorization: Bearer YOUR_CRON_SECRET
Run every 5 minutes for accurate reminder dispatch.
├── ui/ # Next.js frontend
│ ├── app/ # Pages and API routes
│ │ ├── api/cron/remind/ # Reminder cron endpoint
│ │ ├── api/calendar/ # .ics calendar feed
│ │ ├── api/verify/ # Channel verification
│ │ └── dashboard/ # Dashboard page
│ ├── components/ # React components
│ ├── lib/ # Firebase, auth, notifications
│ └── public/ # Favicon, manifest, icons
├── python-workers/ # Docker-based notification workers
│ ├── scheduler/ # Firestore scanner → Redis
│ ├── email_worker/ # Email sender (SMTP)
│ ├── telegram_worker/ # Telegram bot sender
│ ├── discord_worker/ # Discord webhook sender
│ └── docker-compose.yml
├── mcp-server/ # MCP server for AI agents
└── .github/workflows/ # CI/CD