Open In App

Recipe Generator using Next.js

Last Updated : 11 Mar, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

In this tutorial, we’ll create a Recipe Generator App using Next.js, a React framework that allows users to generate random recipes. This type of application can be useful for people looking for new meal ideas or wanting to explore different cuisines. application fetches recipe data from API and displays it to the user.

Output Preview: Let us have a look at how the final output will look like.

gfg-recipe-img

Prerequisites:

Approach to Create Recipe Generator:

  • Setup the Project by Creating a new NextJS project Install the necessary libraries.
  • Design the components for app, including a Navbar, RecipeGenerator, RecipeCard.
  • We will integrate Edamam Api into our app to fetch recipe data.
  • React hooks will be utilized to manage the app’s state, such as search queries, recipes.
  • We will Implement a search feature that allows users to search for recipes based on keywords.
  • Display the fetched recipes in a grid manner, including images, titles, ingredients etc.
  • Bootstrap will be utilized for styling the application.

Steps to Create the Recipe Generator Application:

Step 1: Create a application of NextJS using the following command.

npx create-next-app recipe-generator

Step 2: Navigate to project directory

cd recipe-generator

Step 3: Install the necessary package in your project using the following command.

npm install bootstrap
npm install axios

Step 4: Create the folder structure as shown below and create the files in respective folders.

Project Structure:

Screenshot-(14)

The updated dependencies in package.json file will look like:

"dependencies": {
"axios": "^1.6.7",
"bootstrap": "^5.3.3",
"next": "14.1.0",
"react": "^18",
"react-dom": "^18"
}

Example: Below are the components which describes the implementation of the Recipe Generator.

Javascript




// page.js
 
import RecipeGenerator from '@/components/RecipeGenerator';
import React from 'react';
 
const page = () => {
  return (
    <div>
      <RecipeGenerator />
    </div>
  )
}
 
export default page


Javascript




// Navbar.js
 
import React from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
 
const Navbar = () => {
  return (
    <nav className="nav justify-content-center navbar-light bg-success">
    <li className="nav-item">
    <a className="nav-link text-light" href="#"><h2>GFG Recipe generator</h2></a>
  </li>
 
</nav>
  );
};
 
export default Navbar;


Javascript




// RecipeGenerator.js
 
'use client'
import { useState, useEffect } from 'react';
import axios from 'axios';
import 'bootstrap/dist/css/bootstrap.min.css';
import Navbar from './Navbar';
import RecipeCard from '@/components/RecipeCard';
 
const RecipeGenerator = () => {
  const [recipes, setRecipes] = useState([]);
  const [search, setSearch] = useState('');
  const [selectedRecipe, setSelectedRecipe] = useState(null);
  const APP_ID = 'YOUR_EDAMAM_APP_ID';
  const APP_KEY = 'YOUR_EDAMAM_APP_KEY';
 
  const generateRecipe = async () => {
    try {
      const response = await axios.get(`https://api.edamam.com/search?q=${search}&app_id=bbb0cce2&app_key=2fe683efd1286808ab9fc1d52132e3dd`);
      if (response.data.hits.length > 0) {
        setRecipes(response.data.hits);
      }
    } catch (error) {
      console.error('Failed to fetch recipe', error);
    }
  };
 
  const openModal = (recipe) => {
    setSelectedRecipe(recipe);
    document.getElementById('exampleModal').style.display = 'block';
  };
 
  const closeModal = () => {
    setSelectedRecipe(null);
    document.getElementById('exampleModal').style.display = 'none';
  };
 
  return (
    <>
    <Navbar />
    <div className="container mt-3 justify-content-center">
      <div className="row">
        <div className="col mb-4">
          <input type="text" value={search} onChange={(e) => setSearch(e.target.value)} className="form-control" />
        </div>
        <div className="col">
          <button onClick={generateRecipe} className="btn btn-success justify-content-center">Generate Recipe</button>
        </div>
      </div>
       
        {recipes.length === 0 ? (
          <p>No recipes found</p>
        ) : (
         <RecipeCard recipes={recipes}
         openModal={openModal}
         closeModal={closeModal}
         selectedRecipe={selectedRecipe}
          
         />
        )}
    </div>
    </>
  );
};
 
export default RecipeGenerator;


Javascript




// RecipeCard.js
 
import React from 'react'
import 'bootstrap/dist/css/bootstrap.min.css';
const RecipeCard = ({recipes, openModal, closeModal, selectedRecipe}) => {
  return (
    <div className="row">
        {
            recipes.map((recipe) => (
                <div key={recipe.recipe.label} className="col-md-3 mb-3">
                    <div className="card">
                        <img src={recipe.recipe.image} className="card-img-top" style={{ height: '200px', objectFit: 'cover' }} alt={recipe.recipe.label} />
                        <div className="card-body">
                            <h5 className="card-title">{recipe.recipe.label}</h5>
                            <p className="card-text">Calories: {recipe.recipe.calories.toFixed(2)}</p>
                            <button onClick={() => openModal(recipe)} className="btn btn-outline-success">View Ingredients</button>
                        </div>
                    </div>
                </div>
            ))
        }
        <div className="modal" id="exampleModal" tabIndex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true" onClick={closeModal}>
    <div className="modal-dialog modal-dialog-centered" role="document" style={{ margin: "auto" }}>
        <div className="modal-content" onClick={(e) => e.stopPropagation()}>
            <div className="modal-header">
                <h5 className="modal-title" id="exampleModalLabel">Ingredients{'  '}</h5>
                <button type="button" className="close" data-dismiss="modal" aria-label="Close" onClick={closeModal}>
                    <span aria-hidden="true">×</span>
                </button>
            </div>
            <div className="modal-body">
                <ul>
                    {selectedRecipe && selectedRecipe.recipe.ingredientLines.map((ingredient, index) => (
                        <li key={index}>{ingredient}</li>
                    ))}
                </ul>
            </div>
        </div>
    </div>
</div>
 
    </div>
     
  )
}
 
export default RecipeCard


Start your application using the following command.

npm run dev

Output: Open web-browser and type the following URL http://localhost:3000/

gfg-recipe



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads