# How to Vibe Code Your Own Seats.aero (and Stop Paying for It)

> Real-time award flight availability search engine

- Site: https://seats.aero
- Category: Travel / Developer Tool
- Verdict: **Serious undertaking** (38/100 vibecodeable)
- Estimated effort: 2-3 months of part-time engineering

## Verdict

Build a personal subset with cached mock data, but keep paying for the real product because the scraper maintenance cat-and-mouse game never ends.

The core frontend table search and basic filtering logic are straightforward to scaffold. However, replicating Seats.aero's true value requires reverse-engineering dozens of hostile airline web and mobile endpoints protected by advanced WAFs like Cloudflare and Akamai. Your scrapers will break constantly when airlines tweak their auth tokens or payloads. Building a personal tool that tracks just two or three airlines you personally fly is a rewarding engineering challenge; trying to replicate all 80,000 routes is a full-time job.

### What you can't replicate

- The massive proxy network and bypass infrastructure required to hit airline endpoints without IP blacklists
- The exact internal undocumented API reverse-engineering schemas for 20+ airline loyalty programs
- The historical price and award space trend data accumulated over years of continuous ingestion

## What it does

Continuous background ingestion engine tracking airline award space across global frequent flyer programs for instant search and alerts.

### Core features

- Award flight inventory search across multiple airline programs
- Background worker ingestion pipeline scraping airline endpoints
- Normalized relational database schema for flight dates and routes
- Advanced filtering by cabin class, points cost, and alliance
- Email and SMS alert notification dispatch system
- Developer JSON API with token authentication
- Pro tier gate with 360-day booking window access

## The business

### Pricing

- Free: Free — 60-day advance search window, no registration required
- Pro: $9.99/mo — Full access to annual booking windows, alerts, and API

Founded 2022.
Team size: Solo / Small team.

## The hard parts

- Bypassing aggressive airline bot protections and WAF blocks across 20+ loyalty programs
- Reverse-engineering undocumented airline mobile and web GraphQL/REST endpoints
- Maintaining scrapers when airlines continuously update site layouts or security layers
- Handling millions of daily database upserts and background mutations without table locks

## How to vibe code Seats.aero

### Prerequisites

- Node.js (free): Runtime for the TypeScript backend ingestion workers and web frontend
- GitHub (free): Source code control and GitHub Actions for running scheduled ingestion crons

### Recommended AI tools

- Claude Code: Best-in-class coding agent for scaffolding multi-file database schemas, scraper clients, and API routes
- Cursor: IDE for iterative UI work on the table views, filters, and dashboard components

### Stack

- Frontend: Next.js with Tailwind CSS
- Backend: Next.js API Routes / Node.js worker scripts
- Database: Neon (Serverless Postgres)
- Auth: better-auth
- Payments: Stripe
- Other: Resend for email alerts, Twilio for SMS notifications, Firecrawl for auxiliary site parsing

### Hosting

- Vercel (Hosting the Next.js web application frontend and API routes): $0-20/mo
- Neon (Serverless Postgres database storing routes, flights, and user alert preferences): $0/mo
- Railway (Running long-lived background scraping worker scripts and cron jobs): $5/mo

### Build guide

1. **Database Schema & Project Setup** — Initialize the Next.js project with Tailwind CSS, configure better-auth, and set up the Neon Postgres database schema for routes, flights, and alerts.

```
Initialize a new Next.js project using TypeScript and Tailwind CSS. Configure better-auth with email/password authentication. Connect the app to a Neon serverless Postgres instance using Drizzle ORM. Create the database tables: `routes` (id, origin_airport, destination_airport, airline), `award_flights` (id, route_id, date, cabin_class, mileage_cost, taxes, remaining_seats, updated_at), and `user_alerts` (id, user_id, origin, destination, max_miles, active). Ensure indexes are placed on origin, destination, and date fields for rapid query performance. Write initial migration scripts and test database connectivity.
```

2. **Ingestion Worker Pipeline** — Build resilient Node.js background worker scripts to fetch and normalize award space data from sample airline endpoints, inserting or updating records efficiently.

```
Build a TypeScript background worker module designed to run on Railway via scheduled cron jobs. Implement an ingestion client that targets mock or sample airline award endpoints (or a target test loyalty program). The worker must parse responses, handle HTTP rate limits and exponential backoff retry logic, and perform batch upsert operations into the `award_flights` table in Neon Postgres without causing database table locks. Include structured error logging with Winston or Sentry.
```

3. **Search Interface & Filtering Dashboard** — Develop a high-speed, dense tabular search interface in Next.js optimized for fast data rendering, filtering by route, cabin class, date range, and mileage cost.

```
Create a responsive search dashboard page in Next.js styled with Tailwind CSS, mimicking a fast data-dense table view. Implement search input controls for origin airports, destination airports, date pickers, cabin class dropdowns (Economy, Premium Economy, Business, First), and maximum mileage sliders. Build server-side pagination and sorting endpoints that query the `award_flights` table efficiently using the indexes created in Step 1. Ensure sub-second response times for typical query filters.
```

4. **Alert Engine & Notifications** — Implement the alert management system that checks incoming ingested flight inventory against user criteria and dispatches email/SMS notifications via Resend and Twilio.

```
Build an alert evaluation processor that runs after each successful ingestion batch. The processor must query active records in `user_alerts`, match them against newly discovered or updated `award_flights` entries, and trigger notifications when criteria are met. Integrate the Resend API for sending transactional email alerts and the Twilio API for dispatching SMS notifications. Create a user-facing dashboard page allowing users to view, create, and delete their saved availability alerts.
```

5. **Developer JSON API & Pro Tier Access Control** — Add API token authentication endpoints for developer access and gate extended booking window data behind a subscription check.

```
Implement a protected JSON API route under `/api/v1/search` that authenticates requests using Bearer tokens stored in a new `api_tokens` table linked to users. Enforce access control so that free tier users are restricted to searching flight dates within a 60-day window from the current date, while Pro users with active subscription status can query up to 360 days in advance. Add mock Stripe webhook handler endpoints to update user subscription status upon successful checkout events.
```

### Cost vs paying

**Starting costs (one-time):**

- Domain name registration: $12 one-time
- AI coding assistant subscription: $20 one-time
- Total: ~$32 one-time

**Ongoing costs (monthly):**

- Railway background worker hosting: $5/mo
- Neon database & Vercel frontend: $0/mo
- Twilio SMS & Resend transactional emails: ~$3/mo
- Total: ~$8/mo

- Paying for the SaaS instead: $9.99/mo
- Build time: 40-60 hours
- AI tool credits: $20 (Claude Code / Cursor Pro)
- Break-even: Never (built for learning and personal customization)

## Sources

- [BoringCashCow: One-Man Business Generating $1.5M a Year](https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQEaMIdC4mEiXnOTkKSnh7feQLryGNIjj3fzpappelY1T3TS7yJjmZ7t8l7jUiK0kE5VnNuUAA75gF7IqwL3krh4n3Mxi-8AZwt8CpZWm19LKzt9ij2GI7yeKNlM1kTUFXgV85hz2wSAm_1MKyHMdInDaSCD3LXflTcdOgI=)
- [Seats.aero — About & Documentation Pages](https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFgbb3bjQMXKJtvttvRtOxFVI-WZ7jADjRPGWNwkNn3XzksW1fQYWOL-tRdu6wMmV1V5iMmqwn_qPCR-W1z0q1XLU1Eyofp7itDncaOa_I=)