Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Miguelcds/Recipe-Hub/llms.txt

Use this file to discover all available pages before exploring further.

Recipe Hub follows a layered architecture with a clean separation of concerns. Data flows in one direction — from the external API through services and hooks into pages and finally into presentational components.

Data flow

TheMealDB API

src/services/api.js      — raw fetch calls, response normalization

src/hooks/               — async state management (loading, error, data)

src/pages/               — route-level orchestration

src/components/          — presentational rendering
Each layer has a single responsibility and depends only on the layer below it.

Routing structure

Routing is configured in src/main.jsx using React Router v7’s BrowserRouter, Routes, and Route components. The entire app is wrapped in FavoriteProvider so that favorites state is available on every page.
src/main.jsx
createRoot(document.getElementById("root")).render(
  <StrictMode>
    <FavoriteProvider>
      <BrowserRouter>
        <Routes>
          <Route path="/" element={<App />}>
            <Route index element={<Home />} />
            <Route path="favorites" element={<Favorites />} />
            <Route path="contact" element={<Contact />} />
            <Route path="recipe/:id" element={<RecipeDetail />} />
            <Route path="*" element={<NotFound />} />
          </Route>
        </Routes>
      </BrowserRouter>
    </FavoriteProvider>
  </StrictMode>,
);
FavoriteProvider wraps BrowserRouter, not the other way around. This ensures favorites context is available to all pages rendered inside the router.

App layout shell

App.jsx defines the persistent layout shared across all routes. It renders a header with the site title and navigation, a main content area using <Outlet /> (where child routes render), and a footer.
src/App.jsx
function App() {
  return (
    <>
      <header>
        <h1>The Secret Recipe</h1>
        <h3>Discover, explore and save your favorite recipes</h3>
        <NavBar />
      </header>
      <main>
        <Outlet />
      </main>
      <footer>
        <Footer />
      </footer>
    </>
  )
}
<Outlet /> is the React Router placeholder that renders the matched child route. All pages mount and unmount here while the header and footer remain constant.

Pages

Pages are route-level components. They own data fetching (via hooks) and compose presentational components to build their UI.
PagePathResponsibility
Home/Displays search bar and recipe grid; uses useRecipes for fetch and random recipe logic
RecipeDetail/recipe/:idFetches and displays a single recipe; uses useRecipeDetail with the id URL param
Favorites/favoritesReads favorite IDs from context, renders saved recipes
Contact/contactContact page (currently shows a placeholder message)
NotFound*Shown for any unmatched route

Architecture layers

LayerLocationRole
API servicesrc/services/api.jsFetches from TheMealDB, validates responses, normalizes data shapes
Custom hookssrc/hooks/Manage loading, error, and data state for async operations
Contextsrc/context/Provides global state (favorites) shared across unrelated components
Pagessrc/pages/Orchestrate hooks and compose components for each route
Componentssrc/components/Presentational; receive props and render UI with no direct API or hook calls

Component composition pattern

Pages orchestrate; components are presentational. A page like Home calls useRecipes, holds state, and passes data down:
Home (page)
├── SearchBar — calls onSearch prop → triggers useRecipes.fetchRecipes
└── RecipeList — receives recipes array as prop
    └── RecipeCard × N — receives id, name, picture, category as props
The one exception is RecipeDetailCard, which consumes useFavorites from context directly to toggle favorites inline.