A recipe finder that works from what you already have. Enter the ingredients in your pantry, and ChefReserve searches a database of real recipes, ranks them by how many ingredients you already own, and lets you refine by cuisine, meal type, difficulty, spice level, and cook time.
- You enter your pantry — type ingredients you have, optionally with quantities (e.g.
3 eggs,6 oz beans) - Search — the backend queries Firestore for recipes that contain your ingredients, computes a match % for each, and returns the top 50
- Refine — you can filter and rerank by cuisine, meal type, difficulty, spice level, and max cook time. Groq (Llama 3) reranks the filtered results
- Recipe page — tap any recipe to see the full ingredient list (matched/missing highlighted), step-by-step instructions, and a link to the original source
| Layer | Technology | Hosted on |
|---|---|---|
| Frontend | React + Tailwind CSS | Vercel |
| Backend | Python Flask | Railway |
| Database | Firebase Firestore | Firebase |
| AI — reranking | Groq API (Llama 3.1 8B) | Groq Cloud |
| AI — enrichment | Groq API (Llama 3.1 8B) | Groq Cloud |
| Web crawler | Python (requests + BeautifulSoup) | Run locally |
Recipes are scraped from real cooking websites using the crawler in scripts/crawl_and_scrape.py. The crawler finds all recipe pages on a site by following links from the homepage, extracts structured data from schema.org/Recipe JSON-LD markup, and enriches each recipe with Groq to fill in cuisine, meal type, difficulty, and spice level.
Sites scraped:
Each recipe is stored in Firestore with the following fields: name, source URL, cuisine, meal type, difficulty, spice level, cook time, servings, ingredients list, ingredient tokens (search index), and instructions.
chefreserve/
├── frontend/ React app (Vite)
│ └── src/
│ ├── pages/
│ │ ├── Home.jsx Pantry input
│ │ ├── Results.jsx Recipe list + preference modal
│ │ └── RecipePage.jsx Full recipe detail
│ ├── components/
│ │ ├── RecipeCard.jsx Recipe summary card
│ │ ├── PreferenceModal.jsx Filter/refine UI
│ │ ├── PantryInput.jsx Ingredient input
│ │ └── MatchBadge.jsx Match % badge
│ └── lib/
│ ├── api.js Backend API calls
│ └── firebase.js Firestore client
│
├── backend/ Flask API
│ ├── routes/
│ │ ├── search.py POST /api/search — pantry → candidate recipes
│ │ ├── rerank.py POST /api/rerank — filter + Groq rerank
│ │ └── scraper.py POST /api/scrape — single URL import
│ └── lib/
│ └── firebase_client.py
│
└── scripts/ Run locally
├── crawl_and_scrape.py Bulk crawler + Groq enrichment
└── requirements.txt
- Create a project at console.firebase.google.com
- Enable Firestore in Native mode
- Go to Project Settings → Service Accounts → Generate new private key
- Save the JSON file as
backend/firebase-service-account.json - Copy your web config values to
frontend/.env.local
- Sign up at console.groq.com
- Generate a free API key
- Add
GROQ_API_KEY=your_keyto bothbackend/.envandscripts/.env
cd scripts
pip install -r requirements.txt
python crawl_and_scrape.py https://www.epicurious.com https://www.simplyrecipes.comTuning options (set in scripts/.env):
CRAWL_MAX_PAGES=500 # max pages per site (default 500)
CRAWL_MAX_DEPTH=3 # link depth from homepage (default 3)
CRAWL_DELAY=1.0 # seconds between page fetches (default 1.0)
ENRICH_DELAY=3.0 # seconds between Groq calls (default 3.0)
cd backend
pip install -r requirements.txt
cp .env.example .env # fill in your keys
flask runcd frontend
npm install
cp .env.local.example .env.local # fill in your Firebase config + backend URL
npm run devbackend/.env
FIREBASE_SERVICE_ACCOUNT=path/to/firebase-service-account.json
GROQ_API_KEY=your_groq_key
frontend/.env.local
REACT_APP_BACKEND_URL=http://localhost:5000
REACT_APP_FIREBASE_API_KEY=...
REACT_APP_FIREBASE_AUTH_DOMAIN=...
REACT_APP_FIREBASE_PROJECT_ID=...
scripts/.env
FIREBASE_SERVICE_ACCOUNT=path/to/firebase-service-account.json
GROQ_API_KEY=your_groq_key