Building a Recipe App with NEXT.js and Contentful
In the digital age, cooking has evolved from traditional recipe books to interactive recipe apps. Whether you’re a professional chef or a home cook, having a well-organized recipe app can make your culinary journey smoother and more enjoyable. In this tutorial, we’ll show you how to build your own Recipe App using NEXT.js and Contentful.
1. Why NEXT.js and Contentful?
Before we dive into the development process, let’s briefly discuss why NEXT.js and Contentful make a fantastic combination for building a recipe app.
1.1. NEXT.js: The Perfect Framework
NEXT.js is a popular React framework for building fast, SEO-friendly web applications. It excels in server-side rendering, which means your recipes will load quickly and be easily discoverable by search engines. NEXT.js also provides a great developer experience with features like automatic code splitting, hot module replacement, and routing.
1.2. Contentful: A Headless CMS
Contentful is a powerful headless content management system (CMS) that allows you to create, manage, and deliver content to various platforms and devices. It’s perfect for storing and organizing your recipes, as it provides a user-friendly interface for content creators and a robust API for developers.
Now, let’s start building our Recipe App step by step.
2. Prerequisites
Before we begin, make sure you have the following prerequisites:
- Node.js and npm (Node Package Manager) installed on your computer.
- A Contentful account. You can sign up for free at contentful.com.
- Basic knowledge of React and JavaScript.
Step 1: Setting Up Your NEXT.js Project
Let’s start by creating a new NEXT.js project. Open your terminal and run the following commands:
bash npx create-next-app recipe-app cd recipe-app
This will scaffold a new NEXT.js project called “recipe-app.”
Step 2: Creating Components
Next, we’ll create the components needed for our Recipe App. Inside the “components” directory, create the following files:
- Header.js
- RecipeList.js
- RecipeDetail.js
- Footer.js
Here’s an example of the Header.js component:
jsx // components/Header.js import React from 'react'; const Header = () => { return ( <header> <h1>Recipe App</h1> </header> ); }; export default Header;
You can similarly create the other components and customize them according to your app’s design.
Step 3: Setting Up Routing
To navigate between different sections of our app, we’ll need to set up routing. NEXT.js provides an easy way to do this using the next/link package. First, install the package:
bash npm install next/link
Now, create a pages directory if it doesn’t already exist, and inside it, create the following files:
- index.js
- recipes.js
- recipe/[id].js
Here’s an example of the pages/index.js file:
jsx // pages/index.js import Link from 'next/link'; import Header from '../components/Header'; const Home = () => { return ( <div> <Header /> <h2>Welcome to Recipe App</h2> <Link href="/recipes"> <a>View Recipes</a> </Link> </div> ); }; export default Home;
In the above code, we import the Link component from NEXT.js to create navigation links.
Step 4: Creating the Recipe Data Model
To store and manage our recipes, we’ll define a data model using Contentful. Log in to your Contentful account and create a new content model called “Recipe.” Add the following fields:
- Title (Short Text)
- Description (Long Text)
- Ingredients (Long Text)
- Instructions (Long Text)
- Image (Media)
Once you’ve defined your content model, create some sample recipes using the Contentful web interface.
Step 5: Integrating Contentful
Now that we have our data model in place, it’s time to integrate Contentful into our NEXT.js app. We’ll use the contentful package to fetch data from Contentful.
Install the contentful package:
bash npm install contentful
Create a configuration file to store your Contentful credentials. You can do this by adding a .env.local file to the root of your project with the following content:
env CONTENTFUL_SPACE_ID=your_space_id CONTENTFUL_ACCESS_TOKEN=your_access_token
Replace your_space_id and your_access_token with your actual Contentful space ID and access token.
Next, create a utility function to fetch recipes from Contentful. In the utils directory, create a file called contentful.js:
jsx // utils/contentful.js import { createClient } from 'contentful'; const client = createClient({ space: process.env.CONTENTFUL_SPACE_ID, accessToken: process.env.CONTENTFUL_ACCESS_TOKEN, }); export async function getRecipes() { const entries = await client.getEntries({ content_type: 'recipe' }); return entries.items; }
In this code, we’re using the Contentful SDK to create a client and fetch recipes based on the content type “recipe.”
Step 6: Fetching and Displaying Recipes
With the Contentful integration in place, we can now fetch and display recipes in our app. Let’s modify the pages/recipes.js file:
jsx // pages/recipes.js import React, { useEffect, useState } from 'react'; import Header from '../components/Header'; import { getRecipes } from '../utils/contentful'; const Recipes = () => { const [recipes, setRecipes] = useState([]); useEffect(() => { async function fetchRecipes() { const data = await getRecipes(); setRecipes(data); } fetchRecipes(); }, []); return ( <div> <Header /> <h2>Recipes</h2> <ul> {recipes.map((recipe) => ( <li key={recipe.sys.id}>{recipe.fields.title}</li> ))} </ul> </div> ); }; export default Recipes;
In this code, we use the useState and useEffect hooks to fetch recipes from Contentful when the component mounts and display them as a list.
Step 7: Creating Recipe Detail Pages
To display individual recipe details, we’ll create dynamic pages for each recipe. Modify the pages/recipe/[id].js file as follows:
jsx // pages/recipe/[id].js import React, { useEffect, useState } from 'react'; import { useRouter } from 'next/router'; import Header from '../../components/Header'; import { getRecipe } from '../../utils/contentful'; const RecipeDetail = () => { const router = useRouter(); const { id } = router.query; const [recipe, setRecipe] = useState(null); useEffect(() => { async function fetchRecipe() { const data = await getRecipe(id); setRecipe(data); } if (id) { fetchRecipe(); } }, [id]); if (!recipe) { return <div>Loading...</div>; } return ( <div> <Header /> <h2>{recipe.fields.title}</h2> <p>{recipe.fields.description}</p> <h3>Ingredients</h3> <p>{recipe.fields.ingredients}</p> <h3>Instructions</h3> <p>{recipe.fields.instructions}</p> </div> ); }; export default RecipeDetail;
In this code, we use the useRouter hook from NEXT.js to access the route parameter id and fetch the corresponding recipe from Contentful.
Step 8: Styling Your Recipe App
Styling is an essential part of any web application. You can style your Recipe App using CSS, or if you prefer a more structured approach, you can use a CSS-in-JS solution like styled-components or a CSS framework like Tailwind CSS.
For example, to use styled-components, you can install it with:
bash npm install styled-components
Then, create styled components for your app, such as RecipeCard, RecipeDetailContainer, and so on. Be creative and make your app visually appealing.
Step 9: Deployment
Once you’ve built and styled your Recipe App, it’s time to deploy it to a hosting provider. NEXT.js provides various deployment options, including Vercel, Netlify, and more. Choose the one that suits your needs and follow their deployment instructions.
Conclusion
In this tutorial, we’ve shown you how to create a Recipe App using NEXT.js and Contentful. We covered setting up your NEXT.js project, creating components, setting up routing, integrating Contentful as a headless CMS, fetching and displaying recipes, creating dynamic recipe detail pages, styling your app, and deploying it to the web. With this knowledge, you can expand your app by adding features like user authentication, searching, and user-generated content. Enjoy building your Recipe App, and happy cooking!
Building a Recipe App with NEXT.js and Contentful opens up a world of possibilities for food enthusiasts, chefs, and anyone who loves cooking. By following the steps outlined in this tutorial, you can create a powerful and visually appealing platform to share and discover delicious recipes.
Table of Contents