Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions tutor-finder/.env

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The .env file should be untracked and included in .gitignore
You can try and create a new .env.example file containing the required fields with empty values

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
VITE_SUPABASE_PROJECT_ID="hspjxcouamcdqrvqhkgg"
VITE_SUPABASE_PUBLISHABLE_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImhzcGp4Y291YW1jZHFydnFoa2dnIiwicm9sZSI6ImFub24iLCJpYXQiOjE3Njk2NzI4NzEsImV4cCI6MjA4NTI0ODg3MX0.1A4KloHAiPP6ObODTZnXicntDqMfwDbQP-_FoW4eyUY"
VITE_SUPABASE_URL="https://hspjxcouamcdqrvqhkgg.supabase.co"
Comment on lines +1 to +3
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Do not commit live Supabase credentials.

These values appear to be real project identifiers and a JWT-style key; committing them (especially with VITE_ which ships to clients) is a security risk. Please rotate the keys, move real values to deployment secrets, and keep only placeholders (or an .env.example) in the repo. Removing quotes will also satisfy the dotenv-linter warnings.

🔒 Example placeholder approach
-VITE_SUPABASE_PROJECT_ID="hspjxcouamcdqrvqhkgg"
-VITE_SUPABASE_PUBLISHABLE_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
-VITE_SUPABASE_URL="https://hspjxcouamcdqrvqhkgg.supabase.co"
+VITE_SUPABASE_PROJECT_ID=
+VITE_SUPABASE_PUBLISHABLE_KEY=
+VITE_SUPABASE_URL=
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
VITE_SUPABASE_PROJECT_ID="hspjxcouamcdqrvqhkgg"
VITE_SUPABASE_PUBLISHABLE_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImhzcGp4Y291YW1jZHFydnFoa2dnIiwicm9sZSI6ImFub24iLCJpYXQiOjE3Njk2NzI4NzEsImV4cCI6MjA4NTI0ODg3MX0.1A4KloHAiPP6ObODTZnXicntDqMfwDbQP-_FoW4eyUY"
VITE_SUPABASE_URL="https://hspjxcouamcdqrvqhkgg.supabase.co"
VITE_SUPABASE_PROJECT_ID=
VITE_SUPABASE_PUBLISHABLE_KEY=
VITE_SUPABASE_URL=
🧰 Tools
🪛 dotenv-linter (4.0.0)

[warning] 1-1: [QuoteCharacter] The value has quote characters (', ")

(QuoteCharacter)


[warning] 2-2: [QuoteCharacter] The value has quote characters (', ")

(QuoteCharacter)


[warning] 3-3: [QuoteCharacter] The value has quote characters (', ")

(QuoteCharacter)

🪛 Gitleaks (8.30.0)

[high] 2-2: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.

(jwt)

🤖 Prompt for AI Agents
In `@tutor-finder/.env` around lines 1 - 3, Remove the real Supabase credentials
from the committed .env by replacing VITE_SUPABASE_PROJECT_ID,
VITE_SUPABASE_PUBLISHABLE_KEY, and VITE_SUPABASE_URL with non-sensitive
placeholders (e.g. VITE_SUPABASE_PROJECT_ID=your_project_id) and remove the
surrounding quotes to satisfy dotenv-linter; add a .env.example containing those
placeholders and update deployment to use secure secrets (CI/hosted env vars)
after rotating the exposed keys so the published VITE_ key is no longer valid.

24 changes: 24 additions & 0 deletions tutor-finder/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
Comment on lines +1 to +24
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check for .env files and Supabase integration

echo "=== Checking for .env files in tutor-finder ==="
find tutor-finder -maxdepth 2 -type f -name '.env*' 2>/dev/null | head -20

echo "=== Checking git tracked files that look like env files ==="
git ls-files tutor-finder | grep -E '\.(env|local)$' || echo "No tracked .env files found"

echo "=== Checking for Supabase references in codebase ==="
rg -i 'supabase' tutor-finder --type ts --type tsx --type js --type jsx -l

echo "=== Checking if .env is mentioned anywhere ==="
rg -i '\.env' tutor-finder --type md --type json -l

echo "=== Listing tutor-finder directory structure ==="
ls -la tutor-finder/ | head -30

Repository: tinyfish-io/tinyfish-cookbook

Length of output: 1768


🏁 Script executed:

#!/bin/bash
# Verify what's in the tracked .env file

echo "=== Contents of tracked .env file ==="
cat tutor-finder/.env

echo ""
echo "=== Git history check: when was .env added ==="
git log --oneline --follow tutor-finder/.env | head -5

Repository: tinyfish-io/tinyfish-cookbook

Length of output: 533


Critical: Add .env to .gitignore and remove it from git history.

The .env file is currently tracked in git (commit 1075e30) and contains active Supabase credentials: project ID, publishable key (JWT token), and API URL. These must be removed from the repository immediately.

Required actions:

  1. Add .env and .env.local to .gitignore
  2. Remove the file from git history: git rm --cached tutor-finder/.env and commit
  3. Invalidate the exposed Supabase credentials in your Supabase project settings (the JWT token is now public in git history)
Gitignore update
 node_modules
 dist
 dist-ssr
 *.local
+
+# Environment variables
+.env
+.env.local
+.env.*.local
 
 # Editor directories and files
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Environment variables
.env
.env.local
.env.*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
🤖 Prompt for AI Agents
In `@tutor-finder/.gitignore` around lines 1 - 24, The repo is currently tracking
a sensitive .env with Supabase credentials; update the .gitignore to include
.env and .env.local, remove the tracked .env from Git index (e.g., git rm
--cached .env and commit the change), and purge the secret from history using a
history-rewriting tool (git filter-repo or git filter-branch) targeting the .env
file; after removing the file from history, rotate/invalidate the exposed
Supabase keys in your Supabase project settings to prevent further misuse.

125 changes: 125 additions & 0 deletions tutor-finder/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# Project Title - Exam Tutor Finder

**Live Link**: https://tinyfishtutorsfinder.lovable.app/

## What This Project Is -
The Exam Tutor Finder Tool is an AI-powered tutor discovery and comparison platform that helps students find the best competitive exam tutors from across the web in real time.

Instead of manually searching multiple tutoring websites, this system automatically:

1) Uses AI to discover relevant tutor platforms based on user intent

2) Uses the TinyFish Web Agent to browse tutor websites like a real user

3) Extracts live tutor listings directly from source websites

4) Normalizes tutor data into a structured, comparable format

5) Returns a consolidated list of tutors that can be filtered and compared

The goal is to give students a single place to discover, evaluate, and choose tutors for competitive exams based on exam type, budget, teaching mode, and experience.

## What to Expect

1) Live tutor data extracted directly from real tutoring websites, ensuring up-to-date listings

2) Fast multi-platform search using parallel browser agents

3) Real-time progress updates while tutor websites are being scanned

4) Clean, structured tutor results in standardized JSON format for easy comparison

5) AI-focused matching to show only relevant tutors for selected competitive exams

6) Easy comparison of tutors based on subjects, experience, teaching mode, and pricing

7) Coverage across multiple global tutor marketplaces in one search

8) Scalable system designed to handle multiple websites efficiently

**Demo Video** - https://drive.google.com/file/d/1GOe82HPSTilV_MGob09oexmoiRhEtfbW/view?usp=sharing

## Code snippet -
```bash
const response = await fetch("https://mino.ai/v1/automation/run-sse", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": "sk-mino-YOUR_API_KEY",
},
body: JSON.stringify({
url: "https://www.superprof.com",
goal: "Extract tutor listings for competitive exams (SAT, ACT, AP, GRE, GMAT, Olympiads). Return JSON with tutorName, examsTaught, subjects, teachingMode, location, price, experience, qualifications, contactLink.",
browser_profile: "lite",
}),
});

const reader = response.body!.getReader();
const decoder = new TextDecoder();

while (true) {
const { done, value } = await reader.read();
if (done) break;

const chunk = decoder.decode(value);
for (const line of chunk.split("\n")) {
if (line.startsWith("data: ")) {
const data = JSON.parse(line.slice(6));

if (data.streamingUrl) {
console.log("Live view:", data.streamingUrl);
}

if (data.type === "COMPLETE" && data.resultJson) {
console.log("Tutor Results:", data.resultJson);
}
}
}
}
```

## Tech Stack
**Next.js (TypeScript)**

**Mino API**

**AI**

## Architecture Diagram
```mermaid
flowchart TB

%% =======================
%% UI LAYER
%% =======================
UI["USER INTERFACE<br/>(React + Tailwind + Lovable)"]

%% =======================
%% ORCHESTRATION
%% =======================
ORCH["Tender Search Orchestration Layer<br/>(Next.js API / Server Actions)"]

%% =======================
%% SERVICES
%% =======================
DB["SUPABASE<br/>(Cached Tenders & Metadata)"]
MINO["MINO API<br/>(Browser Automation)"]

%% =======================
%% DETAILS
%% =======================
DBD["• Cached tender listings<br/>• Deduplicated tenders<br/>• Historical records"]
MINOD["• Parallel web agents<br/>• Browse govt tender portals<br/>• Open tender pages<br/>• Extract structured fields<br/>• SSE streaming updates"]

%% =======================
%% CONNECTIONS
%% =======================
UI --> ORCH

ORCH --> DB
ORCH --> MINO

DB --> DBD
MINO --> MINOD
```

Binary file added tutor-finder/bun.lockb
Binary file not shown.
20 changes: 20 additions & 0 deletions tutor-finder/components.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "default",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"css": "src/index.css",
"baseColor": "slate",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
}
}
26 changes: 26 additions & 0 deletions tutor-finder/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import js from "@eslint/js";
import globals from "globals";
import reactHooks from "eslint-plugin-react-hooks";
import reactRefresh from "eslint-plugin-react-refresh";
import tseslint from "typescript-eslint";

export default tseslint.config(
{ ignores: ["dist"] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ["**/*.{ts,tsx}"],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
plugins: {
"react-hooks": reactHooks,
"react-refresh": reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
"react-refresh/only-export-components": ["warn", { allowConstantExport: true }],
"@typescript-eslint/no-unused-vars": "off",
},
},
);
26 changes: 26 additions & 0 deletions tutor-finder/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- TODO: Set the document title to the name of your application -->
<title>Lovable App</title>
<meta name="description" content="Lovable Generated Project" />
<meta name="author" content="Lovable" />

<!-- TODO: Update og:title to match your application name -->
<meta property="og:title" content="Lovable App" />
<meta property="og:description" content="Lovable Generated Project" />
<meta property="og:type" content="website" />
<meta property="og:image" content="https://lovable.dev/opengraph-image-p98pqg.png" />

<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@Lovable" />
<meta name="twitter:image" content="https://lovable.dev/opengraph-image-p98pqg.png" />
</head>

<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
Loading