GreenPlate
ABOUT THIS PROJECT
Cook what you already have, and see what it costs the planet.
Most recipe sites assume you are willing to go shopping. GreenPlate starts from the ingredients already in your kitchen and works outward, and it attaches an eco-score to every result so the environmental impact of a meal is visible before you commit to it. A React front end against a Node backend, with accounts and saved favorites.
A typed API on both sides
Express server in TypeScript with recipe endpoints over GET and POST and full CRUD on favorites through GET, POST, PUT and DELETE. Client and server share the same type definitions, so a change to the recipe shape fails at compile time on both ends rather than at runtime in the browser.
Auth, and removing the hardcoded user
Google sign-in through Firebase with signInWithPopup, and an AuthContext that subscribes to onAuthStateChanged so every page reads the same user object. The first version had a hardcoded user id standing in for a real account; replacing that with the signed-in uid on every favorites request, with the server filtering Firestore on that field, is what turned favorites from a global list into per-user data, and it touched the navbar, the profile page and every favorites route. The server trusts the uid the client sends, which is the first thing to change before real users.
Surviving the API quota
Recipes come from the Spoonacular API, with the detail requests fanned out through Promise.all rather than awaited in sequence, since the search returns ten at a time. The free tier runs out mid-demo, so the recipes route wraps the API call and falls back to recipes stored in Firestore, filtered so every search term matches at least one ingredient. Favorites live in Firestore too, keyed by uid, so accounts and saved recipes survive a server restart, which the in-memory version did not.
The eco-score itself
Every recipe starts at a neutral 5 and is adjusted from its ingredient list and its nutrition data: ingredient categories move it in steps of 4, 2, 1 and -3 depending on how they are produced, then high fiber pulls it down as a plant-based signal and high saturated fat pushes it up as an animal-product one. The result is clamped to 1 through 10 so no single ingredient can blow out the scale.
Where to find it