Skip to content

Commit 1289912

Browse files
KrishnaAgarwal7531krishna7531Simantak Dabhade
authored
Migration restaurant-comparison-tool to Tinyfish SDK (#203)
Removes the last Vite artefact from the App Router migration. src/App.tsx was a near-identical duplicate of src/app/page.tsx left over from the Vite entry point — nothing imported it, now it's gone. Also fixes the README setup flow: setup step now points to .env.example with a cp command instead of instructing users to hand-author a .env.local, and the sign-up link corrected from agent.tinyfish.ai to tinyfish.ai to match .env.example. README fully rewritten to match the current codebase. --------- Co-authored-by: Krishna Agarwal <krishna.laptop3727@gmail.com> Co-authored-by: Simantak Dabhade <simantak@mac.local>
1 parent 2026f35 commit 1289912

56 files changed

Lines changed: 3842 additions & 5942 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
VITE_TINYFISH_API_KEY=your_tinyfish_api_key_here
1+
# TinyFish API key — get yours at https://agent.tinyfish.ai/api-keys
2+
TINYFISH_API_KEY=your-tinyfish-api-key
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"extends": "next/core-web-vitals"
3+
}
Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,9 @@
1-
# Logs
2-
logs
3-
*.log
4-
npm-debug.log*
5-
yarn-debug.log*
6-
yarn-error.log*
7-
pnpm-debug.log*
8-
lerna-debug.log*
9-
10-
node_modules
11-
dist
12-
dist-ssr
13-
*.local
141
.env
15-
16-
# Editor directories and files
17-
.vscode/*
18-
!.vscode/extensions.json
19-
.idea
2+
.env.local
3+
.next/
4+
node_modules/
5+
dist/
6+
build/
207
.DS_Store
21-
*.suo
22-
*.ntvs*
23-
*.njsproj
24-
*.sln
25-
*.sw?
26-
27-
.vercel
8+
*.log
9+
next-env.d.ts
Lines changed: 144 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,115 +1,178 @@
11
# SafeDine
2+
**Live Demo: https://restaurant-comparison-tool.vercel.app**
23

3-
**Live:** [https://restaurant-comparison-tool.vercel.app](https://restaurant-comparison-tool.vercel.app)
4+
**Pre-visit restaurant safety intelligence — AI agents compare 2–5 restaurants simultaneously before you dine.**
45

5-
SafeDine is a pre-visit restaurant safety intelligence tool that compares 2–5 restaurants before dining by analyzing Google Maps reviews, menu photos, and allergen signals. It uses the TinyFish API to dispatch parallel web agents — one per restaurant — that each navigate Google Maps, read 8–12 reviews, check menu images, and return a structured safety report with scores, allergen risks, and dietary suitability ratings.
6+
Enter a city and up to 5 restaurant names, select your allergens and dietary preferences, and SafeDine dispatches one TinyFish browser agent per restaurant in parallel. Each agent navigates Google Maps, reads 8–12 reviews, checks menu photos for allergen signals, and returns a structured safety report. Results stream back as each agent completes.
67

7-
## Demo
8+
## Architecture
89

9-
https://github.com/user-attachments/assets/c684dac5-5e89-43fe-9592-0665a31513f6
10-
11-
12-
## TinyFish API Usage
10+
```
11+
┌─────────────────────────────────────────────────────────────┐
12+
│ Browser (Client) │
13+
│ │
14+
│ SearchForm → AllergenSelector → ComparisonDashboard │
15+
│ (live previews + results stream in) │
16+
└──────────────────────────┬──────────────────────────────────┘
17+
│ POST /api/scrape (one per restaurant, parallel)
18+
│ (SSE — results stream as agents finish)
19+
┌──────────────────────────▼──────────────────────────────────┐
20+
│ Next.js API Route │
21+
│ /api/scrape/route.ts │
22+
│ │
23+
│ TinyFish SDK — client.agent.stream() per restaurant │
24+
│ TINYFISH_API_KEY stored server-side in .env.local │
25+
│ │
26+
│ SSE events: │
27+
│ STREAMING_URL → live browser iframe per agent │
28+
│ STEP → agent progress updates │
29+
│ COMPLETE → structured safety JSON │
30+
│ ERROR → failure message │
31+
└──────────┬──────────────┬──────────────┬────────────────────┘
32+
│ │ │
33+
▼ ▼ ▼
34+
┌────────────┐ ┌────────────┐ ┌────────────┐
35+
│ Google │ │ Google │ │ Google │ ... (2–5)
36+
│ Maps: │ │ Maps: │ │ Maps: │
37+
│ Rest. A │ │ Rest. B │ │ Rest. C │
38+
└────────────┘ └────────────┘ └────────────┘
39+
40+
No database. No cache. Pure in-memory — results fetched live every search.
41+
```
1342

14-
The app calls the TinyFish SSE endpoint once per restaurant, in parallel. Each agent navigates Google Maps, samples reviews for safety signals, checks menu photos for allergen labeling, and returns a structured JSON report:
43+
### TinyFish SDK event flow
1544

16-
```typescript
17-
const response = await fetch("https://agent.tinyfish.ai/v1/automation/run-sse", {
18-
method: "POST",
19-
headers: {
20-
"X-API-Key": import.meta.env.VITE_TINYFISH_API_KEY,
21-
"Content-Type": "application/json",
22-
},
23-
body: JSON.stringify({
24-
url: "https://www.google.com/maps",
25-
goal: `You are a fast food-safety research agent. Investigate "${restaurantName}" in ${city}.
26-
Stay ONLY on Google Maps — do NOT visit external websites.
45+
```
46+
client.agent.stream({ url, goal }, {
47+
onStreamingUrl: (event) => forward iframe URL to client,
48+
onProgress: (event) => forward step description to client,
49+
onComplete: (event) => {
50+
if (event.status === RunStatus.FAILED) → ERROR
51+
else → event.result → structured safety JSON → COMPLETE → SSE
52+
}
53+
})
54+
55+
// for-await drains the stream as fallback
56+
for await (const event of stream) {
57+
if (event.type === EventType.COMPLETE) → handle result
58+
}
59+
```
2760

28-
STEP 1 — FIND THE RESTAURANT on Google Maps:
29-
Search "${restaurantName} ${city}". Confirm the correct listing.
61+
## What Each Agent Extracts
3062

31-
STEP 2 — SAMPLE REVIEWS (keep it fast):
32-
Open the Reviews tab. Read 8–12 recent reviews. Prioritize mentions of:
33-
- Food poisoning, allergic reactions, cross-contamination
34-
- Hygiene, cleanliness, staff responsiveness
35-
Focus on user allergens: ${allergenList}
63+
Each agent navigates Google Maps for the restaurant and returns:
3664

37-
STEP 3 — CHECK MENU IMAGES (if available on Maps):
38-
Look at the Menu tab or Photos section (3–4 images max).
65+
- **Safety score** (0–100) based on review signals and allergen mentions
66+
- **Allergen risks** — detected allergens flagged against your selections
67+
- **Dietary suitability** — vegan, vegetarian, gluten-free, halal, kosher ratings
68+
- **Review highlights** — safety-relevant quotes from real reviews
69+
- **Menu photo analysis** — allergen labeling visible in menu images
70+
- **Confidence level** — how much data the agent found
3971

40-
STEP 4 — RETURN RESULTS as JSON:
41-
{ "restaurantName": "...", "overallSafetyScore": 75,
42-
"allergenRisks": [...], "safetySignals": [...], ... }`,
43-
}),
44-
});
45-
```
72+
## Features
4673

47-
The response streams SSE events including a `streamingUrl` (live view of the agent navigating Google Maps) and a final `COMPLETE` event with the extracted safety data JSON.
74+
- Compare **2–5 restaurants** simultaneously
75+
- Select from **common allergens** (nuts, dairy, gluten, shellfish, etc.)
76+
- Set **dietary preferences** (vegan, vegetarian, halal, etc.)
77+
- Watch **live browser agent iframes** as each agent navigates Google Maps
78+
- Results ranked by safety score — worst risks surfaced first
4879

49-
## How to Run
80+
## Setup
5081

5182
### Prerequisites
5283

5384
- Node.js 18+
54-
- A TinyFish API key ([get one here](https://agent.tinyfish.ai))
55-
56-
### Setup
85+
- TinyFish API key
5786

58-
1. Install dependencies:
87+
### Environment Variables
5988

6089
```bash
61-
cd restaurant-comparison-tool
62-
npm install
90+
cp .env.example .env.local
6391
```
6492

65-
2. Create a `.env` file with your TinyFish API key:
93+
Then fill in:
6694

67-
```
68-
VITE_TINYFISH_API_KEY=your_tinyfish_api_key_here
95+
```env
96+
# TinyFish (required) — https://agent.tinyfish.ai/api-keys
97+
TINYFISH_API_KEY=your-tinyfish-api-key
6998
```
7099

71-
3. Start the dev server:
100+
### Install & Run
72101

73102
```bash
103+
npm install
74104
npm run dev
75105
```
76106

77-
4. Open [http://localhost:5173](http://localhost:5173)
107+
Open http://localhost:3000
78108

79-
## Architecture Diagram
109+
## Project Structure
80110

81111
```
82-
┌──────────────────────────────────────────────────────────────┐
83-
│ User (Browser) │
84-
│ ┌────────────────────────────────────────────────────────┐ │
85-
│ │ React + Vite Frontend (Tailwind + shadcn + Framer) │ │
86-
│ │ │ │
87-
│ │ 1. Enter city + 2–5 restaurant names │ │
88-
│ │ 2. Select allergens & dietary preferences │ │
89-
│ │ 3. Click "Compare Restaurants" │ │
90-
│ │ 4. Watch live browser previews as agents research │ │
91-
│ │ 5. View ranked safety cards + detail panel │ │
92-
│ └────────────────────┬───────────────────────────────────┘ │
93-
└───────────────────────┼──────────────────────────────────────┘
94-
│ POST /v1/automation/run-sse (x N restaurants, parallel)
95-
96-
┌──────────────────────────────────────────────────────────────┐
97-
│ TinyFish API (agent.tinyfish.ai) │
98-
│ │
99-
│ Receives goal prompt + Google Maps URL per restaurant │
100-
│ Spins up a web agent for each request │
101-
│ │
102-
│ SSE Stream Events: │
103-
│ • streamingUrl → live browser preview (iframe) │
104-
│ • STEP → agent progress updates │
105-
│ • COMPLETE → structured safety JSON │
106-
│ • ERROR → failure message │
107-
└────────┬──────────────┬──────────────┬───────────────────────┘
108-
│ │ │
109-
▼ ▼ ▼
110-
┌───────────┐ ┌───────────┐ ┌───────────┐
111-
│ Google │ │ Google │ │ Google │ ... (2–5 restaurants)
112-
│ Maps: │ │ Maps: │ │ Maps: │
113-
│ Rest. A │ │ Rest. B │ │ Rest. C │
114-
└───────────┘ └───────────┘ └───────────┘
112+
restaurant-comparison-tool/
113+
├── src/
114+
│ ├── app/
115+
│ │ ├── layout.tsx # Root layout
116+
│ │ ├── page.tsx # Main UI
117+
│ │ ├── globals.css
118+
│ │ └── api/
119+
│ │ └── scrape/route.ts # POST /api/scrape — SSE + TinyFish per restaurant
120+
│ ├── components/
121+
│ │ ├── search/
122+
│ │ │ ├── SearchForm.tsx # City + restaurant name inputs
123+
│ │ │ ├── AllergenSelector.tsx # Allergen multi-select
124+
│ │ │ ├── PreferenceSelector.tsx # Dietary preference selector
125+
│ │ │ └── RestaurantInput.tsx # Individual restaurant input row
126+
│ │ ├── live/
127+
│ │ │ ├── LiveSearchPanel.tsx # Live agent status panel
128+
│ │ │ ├── LiveBrowserPreview.tsx # Agent iframe grid
129+
│ │ │ ├── RestaurantAgentCard.tsx # Per-agent status card
130+
│ │ │ └── AgentStatusIndicator.tsx # Running/done indicator
131+
│ │ ├── results/
132+
│ │ │ ├── ComparisonDashboard.tsx # Ranked results layout
133+
│ │ │ ├── RestaurantResultCard.tsx # Per-restaurant result card
134+
│ │ │ ├── SafetyScoreRing.tsx # Score visualisation
135+
│ │ │ ├── AllergenRiskPanel.tsx # Allergen risk breakdown
136+
│ │ │ ├── AllergenRiskBadge.tsx # Individual allergen badge
137+
│ │ │ ├── FitExplanation.tsx # Dietary fit explanation
138+
│ │ │ ├── ConfidenceIndicator.tsx # Data confidence level
139+
│ │ │ ├── ResultDetailPanel.tsx # Full detail drawer
140+
│ │ │ ├── GoogleMapsLink.tsx # Link to Google Maps listing
141+
│ │ │ └── AgentLoadingCard.tsx # Skeleton while agent runs
142+
│ │ ├── layout/
143+
│ │ │ ├── Header.tsx
144+
│ │ │ └── Footer.tsx
145+
│ │ └── ui/ # badge, button, card, dialog, input, etc.
146+
│ ├── hooks/
147+
│ │ └── useRestaurantSearch.ts # SSE client + state management
148+
│ ├── context/
149+
│ │ └── SearchContext.tsx # Search state context
150+
│ └── lib/
151+
│ ├── goal-builder.ts # Builds TinyFish goal prompt per restaurant
152+
│ ├── score-calculator.ts # Safety score computation
153+
│ ├── allergens.ts # Allergen definitions
154+
│ ├── tinyfish-client.ts # SDK wrapper
155+
│ ├── constants.ts # App-wide constants
156+
│ └── utils.ts # Shared helpers
157+
├── next.config.ts
158+
└── package.json
115159
```
160+
161+
## Constraint Checklist
162+
163+
| Constraint | Status |
164+
|---|---|
165+
| External database used? | NO (pure in-memory) |
166+
| Cache layer used? | NO (all results fetched live) |
167+
| Scraping parallel? | YES (one `client.agent.stream` per restaurant, all concurrent) |
168+
| Live browser preview? | YES (`onStreamingUrl` → iframe per agent) |
169+
| Allergen risk detection? | YES (review + menu photo analysis) |
170+
| Results ranked? | YES (by safety score, worst risks first) |
171+
172+
## Tech Stack
173+
174+
- **Framework:** Next.js 15 (App Router), TypeScript, Tailwind CSS
175+
- **UI Components:** shadcn/ui
176+
- **Browser Agents:** TinyFish SDK (`client.agent.stream`)
177+
- **Icons:** Lucide React
178+
- **Deployment:** Vercel

restaurant-comparison-tool/components.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"tsx": true,
66
"tailwind": {
77
"config": "",
8-
"css": "src/index.css",
8+
"css": "src/app/globals.css",
99
"baseColor": "neutral",
1010
"cssVariables": true,
1111
"prefix": ""

restaurant-comparison-tool/eslint.config.js

Lines changed: 0 additions & 23 deletions
This file was deleted.

restaurant-comparison-tool/index.html

Lines changed: 0 additions & 16 deletions
This file was deleted.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import type { NextConfig } from "next";
2+
const nextConfig: NextConfig = {};
3+
export default nextConfig;

0 commit comments

Comments
 (0)