|
1 | | -This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). |
| 1 | +<div align="center"> |
| 2 | + |
| 3 | +<img src="public/brightdata.svg" height="40" alt="Bright Data" /> |
| 4 | + × |
| 5 | +<img src="public/yutori.png" height="28" alt="Yutori N1" /> |
| 6 | + |
| 7 | +<br /><br /> |
| 8 | + |
| 9 | +# Ticket Hunter Agent |
| 10 | + |
| 11 | +**An autonomous AI agent that browses the web in real-time to find you the best available tickets — live.** |
| 12 | + |
| 13 | +[](https://vercel.com/new/clone?repository-url=https://github.com/brightdata/ticket-hunter-agent) |
| 14 | +[](https://nextjs.org) |
| 15 | +[](https://typescriptlang.org) |
| 16 | +[](https://tailwindcss.com) |
| 17 | + |
| 18 | +</div> |
| 19 | + |
| 20 | +--- |
| 21 | + |
| 22 | +## What is this? |
| 23 | + |
| 24 | +Ticket Hunter is a **fully autonomous AI agent** that takes a natural-language query like `"Taylor Swift Eras Tour NYC"` and — without any human intervention — searches Google, opens Ticketmaster, StubHub, SeatGeek, and other ticket platforms, navigates the pages, and returns ranked, structured ticket listings in real-time. |
| 25 | + |
| 26 | +The agent streams its work live to the browser: **you watch it browse, click, and extract data as it happens.** |
| 27 | + |
| 28 | +**Built with [Bright Data](https://brightdata.com) + [Yutori N1](https://yutori.com)** |
| 29 | + |
| 30 | +--- |
| 31 | + |
| 32 | +## How it works |
| 33 | + |
| 34 | +The agent runs as a **5-stage LangGraph pipeline**, streamed live to your browser via Server-Sent Events: |
| 35 | + |
| 36 | +``` |
| 37 | +User Query |
| 38 | + │ |
| 39 | + ▼ |
| 40 | +┌─────────────────────────────────────────────────────────┐ |
| 41 | +│ Stage 1 · SERP Search │ |
| 42 | +│ Bright Data SERP API searches Google for ticket sites │ |
| 43 | +│ Scores and selects the top 3 most relevant URLs │ |
| 44 | +└────────────────────────┬────────────────────────────────┘ |
| 45 | + │ |
| 46 | + ▼ |
| 47 | +┌─────────────────────────────────────────────────────────┐ |
| 48 | +│ Stage 2 · Browser Pipeline │ |
| 49 | +│ Connects to Bright Data Scraping Browser via CDP │ |
| 50 | +│ Opens each URL with a real Chromium instance │ |
| 51 | +│ Takes initial screenshot → streamed to UI live │ |
| 52 | +└────────────────────────┬────────────────────────────────┘ |
| 53 | + │ |
| 54 | + ▼ |
| 55 | +┌─────────────────────────────────────────────────────────┐ |
| 56 | +│ Stage 3 · Yutori N1 Agentic Loop (up to 15 steps) │ |
| 57 | +│ N1 vision model views screenshots and decides actions │ |
| 58 | +│ Tools: navigate · click · scroll · type · screenshot │ |
| 59 | +│ Iterates until tickets are found or step limit reached │ |
| 60 | +└────────────────────────┬────────────────────────────────┘ |
| 61 | + │ |
| 62 | + ▼ |
| 63 | +┌─────────────────────────────────────────────────────────┐ |
| 64 | +│ Stage 4 · Structured Extraction │ |
| 65 | +│ OpenRouter (Gemini Flash) extracts JSON from findings │ |
| 66 | +│ Fields: event, date, venue, section, row, price, url │ |
| 67 | +└────────────────────────┬────────────────────────────────┘ |
| 68 | + │ |
| 69 | + ▼ |
| 70 | +┌─────────────────────────────────────────────────────────┐ |
| 71 | +│ Stage 5 · Merge & Rank │ |
| 72 | +│ Deduplicates results across platforms │ |
| 73 | +│ Sorts by price (lowest first) → returned to UI │ |
| 74 | +└─────────────────────────────────────────────────────────┘ |
| 75 | +``` |
| 76 | + |
| 77 | +--- |
| 78 | + |
| 79 | +## Tech Stack |
| 80 | + |
| 81 | +| Layer | Technology | |
| 82 | +|---|---| |
| 83 | +| **Framework** | [Next.js 16](https://nextjs.org) · React 19 · TypeScript 5 | |
| 84 | +| **Styling** | [Tailwind CSS 4](https://tailwindcss.com) | |
| 85 | +| **Agent Orchestration** | [LangGraph](https://langchain-ai.github.io/langgraphjs/) | |
| 86 | +| **Browser Automation** | [Playwright Core](https://playwright.dev) + Chrome DevTools Protocol (CDP) | |
| 87 | +| **Web Infrastructure** | [Bright Data Scraping Browser](https://brightdata.com/products/scraping-browser) + SERP API | |
| 88 | +| **Vision LLM** | [Yutori N1](https://yutori.com) (multimodal, tool-use) | |
| 89 | +| **Extraction LLM** | [OpenRouter](https://openrouter.ai) → Google Gemini Flash | |
| 90 | +| **Rate Limiting** | [Upstash Redis](https://upstash.com) (per-IP, 1 search / 24h for the demo) | |
| 91 | +| **Deployment** | [Vercel](https://vercel.com) via GitHub Actions | |
| 92 | + |
| 93 | +--- |
| 94 | + |
| 95 | +## Supported Ticket Platforms |
| 96 | + |
| 97 | +The agent autonomously detects and browses any of these platforms based on Google results: |
| 98 | + |
| 99 | +- Ticketmaster |
| 100 | +- StubHub |
| 101 | +- SeatGeek |
| 102 | +- Vivid Seats |
| 103 | +- AXS |
| 104 | +- TickPick |
| 105 | +- Gametime |
| 106 | +- Eventbrite |
| 107 | +- Viagogo |
| 108 | +- TicketNetwork |
| 109 | +- Tickets.com |
| 110 | + |
| 111 | +--- |
2 | 112 |
|
3 | 113 | ## Getting Started |
4 | 114 |
|
5 | | -First, run the development server: |
| 115 | +### Prerequisites |
| 116 | + |
| 117 | +- Node.js 18+ |
| 118 | +- A [Bright Data](https://brightdata.com) account with Scraping Browser + SERP API enabled |
| 119 | +- A [Yutori N1](https://yutori.com) API key |
| 120 | +- An [OpenRouter](https://openrouter.ai) API key |
| 121 | +- An [Upstash](https://upstash.com) Redis database (for rate limiting) |
| 122 | + |
| 123 | +### 1. Clone the repo |
| 124 | + |
| 125 | +```bash |
| 126 | +git clone https://github.com/brightdata/ticket-hunter-agent.git |
| 127 | +cd ticket-hunter-agent |
| 128 | +``` |
| 129 | + |
| 130 | +### 2. Install dependencies |
| 131 | + |
| 132 | +```bash |
| 133 | +npm install |
| 134 | +``` |
| 135 | + |
| 136 | +### 3. Configure environment variables |
| 137 | + |
| 138 | +Create a `.env.local` file in the project root: |
| 139 | + |
| 140 | +```env |
| 141 | +# Yutori N1 — vision LLM for autonomous browsing |
| 142 | +YUTORI_API_KEY=your_yutori_api_key |
| 143 | +
|
| 144 | +# Bright Data — Scraping Browser CDP WebSocket endpoint |
| 145 | +# Found in your Bright Data dashboard under Scraping Browser > Access Parameters |
| 146 | +BRD_CDP_URL=wss://brd-customer-<id>-zone-<zone>:<password>@brd.superproxy.io:9222 |
| 147 | +
|
| 148 | +# Bright Data — API key for SERP and Web Unlocker |
| 149 | +BRIGHTDATA_API_KEY=your_brightdata_api_key |
| 150 | +BRIGHTDATA_SERP_ZONE=serp # optional, defaults to "serp" |
| 151 | +BRIGHTDATA_WEB_UNLOCKER_ZONE=unblocker # optional, defaults to "unblocker" |
| 152 | +
|
| 153 | +# OpenRouter — structured JSON extraction via Gemini Flash |
| 154 | +OPENROUTER_API_KEY=your_openrouter_api_key |
| 155 | +OPENROUTER_MODEL=google/gemini-flash-1.5 # optional |
| 156 | +
|
| 157 | +# Upstash Redis — rate limiting (remove or leave blank to disable) |
| 158 | +KV_REST_API_URL=https://your-instance.upstash.io |
| 159 | +KV_REST_API_TOKEN=your_upstash_token |
| 160 | +``` |
| 161 | + |
| 162 | +### 4. Run locally |
6 | 163 |
|
7 | 164 | ```bash |
8 | 165 | npm run dev |
9 | | -# or |
10 | | -yarn dev |
11 | | -# or |
12 | | -pnpm dev |
13 | | -# or |
14 | | -bun dev |
15 | 166 | ``` |
16 | 167 |
|
17 | | -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. |
| 168 | +Open [http://localhost:3000](http://localhost:3000) and search for any event. |
| 169 | + |
| 170 | +--- |
| 171 | + |
| 172 | +## Project Structure |
| 173 | + |
| 174 | +``` |
| 175 | +src/ |
| 176 | +├── app/ |
| 177 | +│ ├── api/search/route.ts # POST endpoint — SSE stream orchestrator |
| 178 | +│ ├── page.tsx # Main UI page |
| 179 | +│ └── layout.tsx # Root layout + global metadata |
| 180 | +├── components/ |
| 181 | +│ ├── SearchForm.tsx # Query input with example prompts |
| 182 | +│ ├── BrowserView.tsx # Live browser screenshot panels (1–3 platforms) |
| 183 | +│ ├── StatusLog.tsx # Real-time agent activity log |
| 184 | +│ └── ResultCard.tsx # Ticket card with price, venue, seats |
| 185 | +├── hooks/ |
| 186 | +│ └── useTicketSearch.ts # SSE consumer + client state management |
| 187 | +└── lib/ |
| 188 | + ├── agent/ |
| 189 | + │ ├── graph.ts # LangGraph workflow definition |
| 190 | + │ ├── state.ts # Agent state schema |
| 191 | + │ ├── stream-events.ts # SSE event emitters |
| 192 | + │ ├── runtime-session.ts # Browser session lifecycle |
| 193 | + │ ├── browser-utils.ts # Playwright helpers |
| 194 | + │ ├── tools.ts # N1 tool schemas (click, scroll, etc.) |
| 195 | + │ └── nodes/ |
| 196 | + │ ├── serp-search.ts # Stage 1: Google SERP via Bright Data |
| 197 | + │ ├── browser-open.ts # Stage 2: CDP browser connection |
| 198 | + │ ├── browser-pipeline.ts # Stage 2: per-URL browsing orchestration |
| 199 | + │ ├── n1-browse-core.ts # Stage 3: N1 agentic loop (15-step max) |
| 200 | + │ ├── n1-browse.ts # Stage 3: N1 LangGraph node wrapper |
| 201 | + │ ├── extract.ts # Stage 4: structured JSON extraction |
| 202 | + │ └── merge-and-rank.ts # Stage 5: dedup + price sort |
| 203 | + ├── bright-data.ts # Bright Data SDK wrapper |
| 204 | + ├── n1-client.ts # Yutori N1 OpenAI-compatible client |
| 205 | + ├── openrouter-client.ts # OpenRouter extraction client |
| 206 | + ├── rate-limit.ts # Upstash Redis rate limiter |
| 207 | + └── types.ts # Shared TypeScript interfaces |
| 208 | +``` |
| 209 | + |
| 210 | +--- |
| 211 | + |
| 212 | +## Deployment |
| 213 | + |
| 214 | +The repo includes a GitHub Actions workflow for automatic Vercel deployment. |
| 215 | + |
| 216 | +### Deploy to Vercel (one-click) |
| 217 | + |
| 218 | +[](https://vercel.com/new/clone?repository-url=https://github.com/brightdata/ticket-hunter-agent) |
| 219 | + |
| 220 | +Then add all environment variables in your Vercel project settings. |
| 221 | + |
| 222 | +### Deploy via GitHub Actions |
| 223 | + |
| 224 | +1. Fork the repo |
| 225 | +2. Connect it to a Vercel project |
| 226 | +3. Add these secrets to your GitHub repo: |
| 227 | + - `VERCEL_TOKEN` |
| 228 | + - `VERCEL_ORG_ID` |
| 229 | + - `VERCEL_PROJECT_ID` |
| 230 | +4. Add all `.env.local` variables to Vercel's environment settings |
| 231 | +5. Push to `main` — the workflow deploys automatically |
| 232 | + |
| 233 | +### Manual CLI deploy |
| 234 | + |
| 235 | +```bash |
| 236 | +npm run build |
| 237 | +npx vercel deploy --prod |
| 238 | +``` |
| 239 | + |
| 240 | +--- |
| 241 | + |
| 242 | +## Ticket Result Schema |
| 243 | + |
| 244 | +Each result returned by the agent follows this structure: |
| 245 | + |
| 246 | +```typescript |
| 247 | +interface TicketResult { |
| 248 | + eventName: string; // "Taylor Swift | The Eras Tour" |
| 249 | + eventDate: string; // "Friday, June 7, 2025" |
| 250 | + venue: string; // "MetLife Stadium" |
| 251 | + city: string; // "East Rutherford, NJ" |
| 252 | + ticketType: string; // "Floor A · General Admission" |
| 253 | + section: string; // "GA Floor" |
| 254 | + row: string; // "N/A" |
| 255 | + seats: string; // "2 available" |
| 256 | + quantity: number; // 2 |
| 257 | + price: string; // "$380" |
| 258 | + currency: string; // "USD" |
| 259 | + platform: string; // "StubHub" |
| 260 | + url: string; // Deep link to the listing |
| 261 | + notes: string; // Any additional context |
| 262 | +} |
| 263 | +``` |
| 264 | + |
| 265 | +--- |
| 266 | + |
| 267 | +## Real-Time Streaming |
| 268 | + |
| 269 | +The agent communicates with the frontend via **Server-Sent Events (SSE)**. Events emitted during a search: |
| 270 | + |
| 271 | +| Event | Payload | Description | |
| 272 | +|---|---|---| |
| 273 | +| `status` | `{ message, level }` | Agent log entry (INFO, ACTION, WARN, DONE, etc.) | |
| 274 | +| `screenshot` | `{ data, source }` | Base64 browser screenshot streamed live | |
| 275 | +| `inspect_url` | `{ url, source }` | Current URL the browser has navigated to | |
| 276 | +| `result` | `{ tickets, finalAnswer }` | Final structured ticket results | |
| 277 | +| `error` | `{ message }` | Agent error | |
| 278 | +| `done` | — | Stream complete | |
| 279 | + |
| 280 | +--- |
| 281 | + |
| 282 | +## Rate Limiting |
| 283 | + |
| 284 | +The live demo enforces **1 search per IP per 24 hours** via Upstash Redis. |
| 285 | + |
| 286 | +When running locally with your own keys, this limit is not enforced unless you configure Upstash in your `.env.local`. |
| 287 | + |
| 288 | +--- |
| 289 | + |
| 290 | +## Powered by |
| 291 | + |
| 292 | +<table> |
| 293 | +<tr> |
| 294 | +<td width="50%" valign="top"> |
| 295 | + |
| 296 | +### Bright Data |
| 297 | + |
| 298 | +[Bright Data](https://brightdata.com) provides the web infrastructure that makes the agent possible: |
18 | 299 |
|
19 | | -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. |
| 300 | +- **Scraping Browser** — a real Chromium instance with residential proxy routing, anti-bot bypass, and JavaScript execution, connected via CDP |
| 301 | +- **SERP API** — reliable Google search results to discover the right ticket platform URLs |
20 | 302 |
|
21 | | -This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. |
| 303 | +</td> |
| 304 | +<td width="50%" valign="top"> |
22 | 305 |
|
23 | | -## Learn More |
| 306 | +### Yutori N1 |
24 | 307 |
|
25 | | -To learn more about Next.js, take a look at the following resources: |
| 308 | +[Yutori N1](https://yutori.com) is the multimodal vision LLM at the core of the agent loop: |
26 | 309 |
|
27 | | -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. |
28 | | -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. |
| 310 | +- Receives browser screenshots as visual input |
| 311 | +- Decides which actions to take (click, scroll, navigate, type) |
| 312 | +- Extracts ticket information from what it sees |
| 313 | +- Runs up to 15 reasoning steps per URL |
29 | 314 |
|
30 | | -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! |
| 315 | +</td> |
| 316 | +</tr> |
| 317 | +</table> |
31 | 318 |
|
32 | | -## Deploy on Vercel |
| 319 | +--- |
33 | 320 |
|
34 | | -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. |
| 321 | +## License |
35 | 322 |
|
36 | | -Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. |
| 323 | +MIT © [Bright Data](https://brightdata.com) & [Yutori](https://yutori.com) |
0 commit comments