Recipe Discovery App
Overview
For this project, you will build a client-side “Recipe Discovery” application. This project will serve as a comprehensive demonstration of your mastery of advanced React concepts. The application will allow users to browse recipes by category, search for specific recipes, view detailed recipe information, and manage a personal list of “favorite” recipes.
You will use a free, public API for recipe data and implement a varietys of hooks, state management patterns, and routing solutions to create a feature-rich, single-page application (SPA).
Time Allocation
- In-class time: 3.5 hours
- Outside of class: At instructor’s discretion
Core Requirements
You will build a Recipe Discovery application using the TheMealDB API (a free API, no key required).
1. State Management & Data Fetching
- Use the
useState
anduseEffect
hooks to fetch and display data from the API. - Your application should manage loading and error states gracefully, displaying appropriate UI indicators to the user (e.g., a loading spinner, an error message).
2. Custom Hooks
You must create and implement at least two custom hooks:
useFetch
(or similar): A generic custom hook for handling data fetching logic. It should manage the data, loading state, and error state. This hook will be used throughout your application to communicate with the API.useLocalStorage
: A custom hook to synchronize a piece of state with the browser’slocalStorage
. This will be used to persist the user’s list of favorite recipes.
3. Global State with Context API
- Create a
FavoritesContext
to manage the user’s list of favorite recipes globally. - The context must provide:
- A list of favorite recipe IDs.
- A function to add a recipe to favorites.
- A function to remove a recipe from favorites.
- A function to check if a recipe is already in favorites.
- This context should use your
useLocalStorage
hook internally to persist the favorites list across browser sessions.
4. Routing
Your application must include the following pages and routing logic:
- Home Page (
/
):- Displays a grid or list of all available recipe categories fetched from the API.
- Each category should be a link that navigates to its respective category page.
- Category Page (
/category/[categoryName]
):- A dynamic route that displays all recipes belonging to the category specified in the URL (e.g.,
/category/Seafood
). - Each recipe shown should be a link to its detailed recipe page.
- A dynamic route that displays all recipes belonging to the category specified in the URL (e.g.,
- Recipe Detail Page (
/recipe/[recipeId]
):- A dynamic route that fetches and displays the full details for a single recipe (image, ingredients, instructions, etc.).
- This page must include a button to “Add to Favorites” or “Remove from Favorites”. The button’s state and action should be handled by your
FavoritesContext
.
- Favorites Page (
/favorites
):- Displays a list of all recipes that the user has marked as a favorite.
- If the user has no favorites, this page should display a message prompting them to browse and add some.
- Search Functionality:
- A search bar, likely in a shared Navbar, that allows users to search for recipes by name.
- Submitting a search should navigate the user to a search results page (e.g.,
/search?query=Arrabiata
). This page will display the results of the search query.
5. Components & UI
- Create reusable, well-styled components (e.g.,
RecipeCard
,Navbar
,Spinner
,ErrorMessage
). - The application should be visually appealing and responsive. Use of a CSS framework, CSS-in-JS, or CSS Modules is up to you.
TheMealDB API Endpoints
The following endpoints are available for use, but are only examples. You will need to explore the API documentation and use the endpoints that best fit the needs of your application.
- List all categories:
https://www.themealdb.com/api/json/v1/1/categories.php
- Filter by category:
https://www.themealdb.com/api/json/v1/1/filter.php?c=Seafood
- Lookup full recipe details by ID:
https://www.themealdb.com/api/json/v1/1/lookup.php?i=52772
- Search meal by name:
https://www.themealdb.com/api/json/v1/1/search.php?s=Arrabiata
Submission Guidelines
- GitHub Repository: A link to a public GitHub repository containing the complete source code for your project.
- README.md: The repository must include a
README.md
file that contains:- A brief description of the application and its features.
- Instructions on how to install dependencies and run the project locally.
- Reflection: A short section in your
README.md
or in a separateREFLECTION.md
file detailing:- The most challenging part of the project for you.
- A brief explanation of a design decision you made (e.g., why you structured a hook a certain way, how you decided to manage a piece of state).
Rubric for Evaluation
Criteria | Excellent (18-20 pts) | Good (15-17 pts) | Fair (12-14 pts) | Needs Improvement (0-11 pts) |
---|---|---|---|---|
State & Data Fetching | All API data is fetched correctly with useEffect . Loading and error states are handled gracefully across the entire application with clear user feedback (spinners, messages). | Most data is fetched correctly. Loading/error states are present but may be missing in some areas or could offer better user feedback. | Data fetching is functional but has significant issues. Loading/error states are largely unhandled, leading to a poor user experience. | Core data fetching is broken or missing. Application is not usable due to data failing to load. |
Custom Hooks | useFetch and useLocalStorage hooks are created, implemented correctly, and are effectively generic and reusable. The code is clean and follows the Rules of Hooks. | Both hooks are created and functional. One or both might lack some reusability, have minor bugs, or could be implemented more cleanly. | One or both hooks are attempted but have significant flaws, are not reusable, or are not used correctly throughout the application. | Custom hooks are not implemented or are fundamentally non-functional. |
Context API (Global State) | FavoritesContext is implemented flawlessly. It correctly uses useLocalStorage for persistence. Add, remove, and check functions work perfectly across all relevant components. State is always in sync. | FavoritesContext is functional. There may be minor bugs in state updates or persistence. The logic might be slightly inefficient but works for the main use cases. | FavoritesContext is present but has major issues. State may not persist correctly, or functions to update state are buggy. UI is not always in sync with the state. | FavoritesContext is not implemented or is completely broken, making the “favorites” feature non-functional. |
Routing (Dynamic & Static) | All specified routes (/ , /category/[name] , /recipe/[id] , /favorites , /search ) are implemented correctly. Dynamic routes correctly use params to display data. Navigation is seamless. | Most routes are functional. There may be a minor issue with one route, or the implementation of dynamic routing could be improved (e.g., “not found” cases might be missing). | Several routes are missing or broken. Dynamic routing is attempted but fails in common cases. Navigation flow is confusing or buggy. | Core routing is non-functional. It is not possible to navigate the application as required. |
Code Quality & UI | Code is clean, well-organized, and highly reusable. File structure is logical. The UI is polished, responsive, and intuitive. Components are well-defined and follow a clear separation of concerns. | Code is mostly organized and readable. Some components could be more reusable. The UI is functional and responsive, but may lack polish. | Code is disorganized and hard to follow. Components have mixed concerns. The UI is functional on desktop but is not responsive or has significant visual bugs. | Code is messy and non-reusable. The UI is broken, non-responsive, or very difficult to use. |