← back to all projects
Recipe Exchange (GraphQL Full Stack)
Part 8 — GraphQL
Why This Project
A recipe exchange is a natural fit for GraphQL because recipes have deeply nested
data: a recipe has ingredients (each with a name, amount, unit), steps (ordered),
tags, an author, and reviews from other users. With REST you'd either over-fetch
(get everything) or make multiple requests. With GraphQL, the frontend asks for
exactly the fields it needs. This project covers both the backend (Apollo Server)
and frontend (Apollo Client) in one go.
What to Build
A platform where users share recipes. Browse recipes by cuisine or ingredient,
view detailed recipe pages, submit your own recipes, and leave ratings/reviews on
others' recipes. Logged-in users can save recipes to a personal collection.
Real-time: when someone posts a new recipe, other users browsing the site see
it appear via subscriptions.
Requirements
- Backend (Apollo Server + Express + MongoDB):
- Types: User, Recipe (title, description, ingredients[], steps[], cuisineType, cookTime, author), Review (rating, comment, author, recipe)
- Queries: allRecipes (with filters: cuisine, ingredient, minRating), recipe(id), me, myCollection
- Mutations: addRecipe, editRecipe, deleteRecipe (only author), addReview, saveToCollection, removeFromCollection, createUser, login
- Subscription: recipeAdded
- Computed field: averageRating on Recipe type (resolved from reviews)
- Auth: JWT via context — only logged-in users can mutate
- N+1 awareness: recipe → author resolution, recipe → reviews resolution
- Frontend (React + Apollo Client):
- Browse page: grid of recipe cards with filters (cuisine, ingredient search)
- Recipe detail page: full recipe with ingredients, steps, reviews, average rating
- Submit recipe form with dynamic ingredient/step fields (add/remove rows)
- My Collection page: saved recipes
- Apollo cache update after adding a recipe or review
- useSubscription: new recipes appear in browse page in real time
- React Router for navigation
Skills Practiced
GraphQL schema design
Apollo Server
Apollo Client
resolvers
mutations
subscriptions
computed fields
Apollo cache
query variables
dynamic forms
Pain Point to Notice
The dynamic ingredient/step form on the frontend is tricky — you need to manage an
array of objects in form state, with add/remove buttons for each row. This is a
common real-world pattern that FSO doesn't cover. On the backend, pay attention to
how the schema shapes your API surface. Unlike REST, you can't just add a new
endpoint — you extend the schema, which forces you to think about your data graph
holistically.