Code: github.com/punitarani/flights-tracker

Overview
GrayPane is a full‑stack flight discovery and alerting system. It enables users to search routes, track fare trends, explore award availability (via seats.aero), and receive scheduled email alerts. The app uses a typed API layer, durable background workflows, and a PostgreSQL schema designed for idempotent processing and auditability.
- Frontend: Next.js 15, React 19, Tailwind CSS, Radix UI, TanStack Query, next-themes, Sonner
- API: tRPC routers with Zod validation, Next.js Server Actions
- Workers: Cloudflare Workers + Workflows + Queues for alert processing and seats.aero ingestion
- DB: PostgreSQL via Drizzle ORM with prefixed ULID identifiers; JSONB alert filters
- Auth: Supabase with SSR
- Email: Resend for notifications
- Observability: Sentry for errors and performance
- Tooling: TypeScript, Bun test runner, Biome formatter/linter

System Architecture
At a high level, the system separates user‑facing interactions from durable background processing:
- User interacts with the Next.js app (search flights, manage alerts)
- API layer (tRPC) validates inputs, persists data, and orchestrates background work
- Cloudflare Workflows run on cron and via queues to process alerts at scale
- Workers call the app’s flight API for fresh data, apply alert rules, and send emails via Resend
Architecture Diagram (Workers Flow)

API & Service Layer
- tRPC Routers:
src/server/routers/*provide typed endpoints for alerts, flights, airports, and seats.aero integration - Validation: Zod schemas (e.g., versioned filters) ensure safe, forward‑compatible inputs
- Server Actions: Mutations use Next.js server actions where appropriate for minimal overhead
Core Services (Shared Between App and Workers)
Core business logic is implemented under src/core/ and reused by Workers via thin adapters:
alerts-service.ts– high‑level alert operationsalerts.db.ts,notifications.db.ts– DB operationsseats-aero.db.ts– award availability data managementfilters.ts,alert-filter-utils.ts,alert-defaults.ts– versioned, typed alert filter modelalert-processing-service.ts,alert-flight-fetcher.ts– flight matching and fetching orchestration
Adapters in src/workers/adapters/ wrap these services for the Worker runtime, keeping Cloudflare‑specific code small.
Data Model Highlights
- Alerts: Persisted with JSONB filter payloads (versioned) for schema agility
- Notifications: Email sends recorded for 24‑hour gating and audit
- Seats.aero: Requests and individual trips stored to support async fetching and incremental progress
Alert Processing (Cloudflare Workers)
- Workflows:
check-flight-alertsandprocess-flight-alertscoordinate user batching and per‑user processing - Queues:
flights-tracker-alerts-queuelimits concurrency (10 users) and enables backpressure - Idempotency: Workflow instance IDs encode user and date; duplicates are safely ignored
- Time Windows: Email delivery only within 18:00–21:59 UTC and max once per 24h per user
- Observability: Sentry traces, logs, and error capture across handlers and steps
Seats.aero Async Search
A dedicated Workflow seats-aero-search processes award availability:
- Triggered by a tRPC call → Worker HTTP endpoint
- Paginates seats.aero API, stores trips in DB, and updates progress
- Frontend polls status (TanStack Query) until completion for a smooth UX
Engineering Practices
- Type-safety end-to-end: tRPC + Zod + Drizzle keep contracts, validation, and schema aligned
- Observability by default: Sentry traces span API and Workers for root-cause analysis
- Deterministic workflows: Idempotent instance IDs and explicit email gating windows
- Fast feedback: Bun tests for Workers and core modules run in <100ms locally
- Single-package reuse: Workers import
src/core/*to avoid duplication
End-to-End Flow (User Perspective)
- Create alert(s) with typed filters (route, dates, price, cabin, stops)
- Cron schedules per-user processing via Cloudflare Queue (max 10 concurrent)
- Worker fetches fresh flights, matches filters, dedupes, records notification
- If eligible (6–9 PM UTC, >24h since last email), send a single daily email
References
- Source:
punitarani/flights-tracker - Workers design:
docs/workflows.md - Core modules:
src/core/* - Worker adapters/utils:
src/workers/adapters/*,src/workers/utils/*