---
title: "Build a modern restaurant website with Contentful and Next 12"
description: "Learn how to use Contentful and Next.js 12 to build a modern restaurant website."
source: "https://www.netlify.com/blog/2021/10/19/build-a-modern-restaurant-website-with-contentful-and-next.js-12/"
last_updated: "2026-07-28T14:07:09.000Z"
---
Hey there!

Have you ever built a website that pulls content from Contentful? In this blog post, I’m gonna show you how to integrate this CMS with Next.js 12 to build a modern restaurant demo site.

## Common ground

The Developer Experience team at Netlify decided to work on integrating Contentful with different frontend frameworks. To make it easier, we decided to share the same data layer and style guide. This way, each demo site uses a custom npm package that fetches data from the Contentful API and uses it as a [Netlify Build Plugin](https://docs.netlify.com/configure-builds/build-plugins/), and another shared module to get the stylesheets.

The main goal was to be able to:

-   Build a demo site with a couple of pages
-   Fetch some menu data for a restaurant
-   Display the menu data with titles, descriptions, prices, pictures, etc.
-   Fetch data about the restaurant’s details (contact, address) and display them
-   Use a common style guide for all demos

If you’d like to know more about our decision to build a shared data layer, check out [this great blog post](https://netlify.com/blog/2021/10/20/learning-to-future-proof-sites-using-headless-cms-and-different-ssgs/) and [the open-source repo](https://github.com/netlify/demo-restaurant-sites-data)!

## Setting up Contentful

To use Contentful, you need to create an account and generate a couple of tokens.

Start by [creating an account](https://www.contentful.com/) if you don’t already have one.

Then, under `Settings` in the menu bar, click on `API keys` to add a key for your project.

Give your project a name and description, the `space ID`and `Content API` access tokens will be automatically generated.

Once this is done, you can move on to using these tokens to get content for your app.

## Fetching content with the Contentful API

Fetching content from the Contentful API can be done in a small amount of code. What you mainly need is to require the `contentful` package, and use the space ID and access token to be able to access the data you entered in the CMS.

For example, here’s a code sample to fetch some menu data:

```
// initial setup providing the space ID and access tokenconst client = require("contentful").createClient({  space: process.env.CONTENTFUL_SPACE_ID,  accessToken: process.env.CONTENTFUL_CONTENT_API_TOKEN});
const fetchMenu = async () => {  // Querying the entries specifying the content type ID  const entries = await client.getEntries({    content_type: "menuItem"  });
  // Formatting the data the way we'd like to access it in the UI  let menu = [];  for (item in entries.items) {    let thisItem = entries.items[item];    menu.push({      title: thisItem.fields.title,      description: thisItem.fields.description,      price: thisItem.fields.price,      currency: thisItem.fields.currency,      category: thisItem.fields.category,      dietary: {        vegan: thisItem.fields.vegan,        vegetarian: thisItem.fields.vegetarian,        glutenFree: thisItem.fields.glutenFree      }    });  }
  return menu;};
return await fetchMenu();
```

Even though we decided to use this architecture for reusability between demo projects, you can also run it in a [Netlify Function](https://www.netlify.com/products/functions/)!

## Setting up Next.js

To build this demo site using Next.js, I started by installing the required packages with `npm install next`.

The restaurant site has 2 pages so I created 2 files under the `pages` folder (`index.js` and `menu.js`) so that the `/` and `/menu` routes would be automatically available.

From there, I created different components for the various parts of the UI, using React.js and CSS-in-JS.

To pull the data locally, I started by running `netlify build` using the [Netlify CLI](https://docs.netlify.com/cli/get-started/) to trigger the `onPreBuild` event that runs our Build Plugin. I then imported the JSON files generated. For example, the component responsible for displaying the restaurant information looks like this:

```
import info from "../data/info.json";
export default function RestaurantInfo() {  return (    <section className="restaurant-info">      <h1>About:</h1>      <section className="details">        <p>{info.contact.streetAddress.join(" ")}</p>        <p>{info.contact.phone}</p>      </section>
      <h1>Hours: </h1>      {info.hours.map((h, i) => (        <ul key={i}>          <li>{h}</li>        </ul>      ))}    </section>  );}
```

After getting the data and structuring the components, I moved on to styling.

## Styling it up

As our site has a common layout across pages that includes a sidebar with info and a main content area, I import the common stylesheet in my Layout component:

```
// We did not publish our module as an npm package so we use the relative path to import itimport "../node_modules/contentfull-belly-styles/styles.css";
```

From there I’m able to use the classes indicated in the [`contentful-belly-styles` repo](https://github.com/netlify/contentfull-belly-styles) and have my restaurant site styled automatically.

If I want to add some custom styles, I can also do that using CSS-in-JS. For example, I can add the following styles to change the padding and margin of my restaurant’s info component.

```
<style jsx>{`  ul {    margin: 0px;    padding: 2px 5px;  }
  .restaurant-info {    padding: 5px;  }`}</style>
```

## Demo

If you’d like to play around with this, feel free to [have a look at the demo site](https://demo-restaurant-contentful-next.netlify.app/).

You can also have a look at the [repo on GitHub](https://github.com/charliegerard/demo-restaurant-contentful-next) or deploy this template directly to Netlify by clicking on the button below!

[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/charliegerard/demo-restaurant-contentful-next)

### Share

-   [X (fka Twitter)](https://twitter.com/intent/tweet?text=Build a modern restaurant website with Contentful and Next.js 12&url=https://www.netlify.com/blog/2021/10/19/build-a-modern-restaurant-website-with-contentful-and-next.js-12//)
-   [LinkedIn](https://www.linkedin.com/shareArticle?mini=true&url=https%3A%2F%2Fwww.netlify.com%2Fblog%2F2021%2F10%2F19%2Fbuild-a-modern-restaurant-website-with-contentful-and-next.js-12%2F%2F)
-   [Facebook](https://www.facebook.com/sharer.php?u=https://www.netlify.com/blog/2021/10/19/build-a-modern-restaurant-website-with-contentful-and-next.js-12//)
-   [Bluesky](https://bsky.app/intent/compose?text=Build a modern restaurant website with Contentful and Next.js 12+https://www.netlify.com/blog/2021/10/19/build-a-modern-restaurant-website-with-contentful-and-next.js-12//)

* * *

### Tags

-   [Contentful](/blog/tags/contentful/)
-   [Next.js](/blog/tags/next.js/)
-   [Frontend](/blog/tags/frontend/)

## Keep reading

![](/_astro/3f45eb6eda4ea8814be310e3df4a7883a5bd9ba0-1200x675_ZcBDUS.webp)

Guides & Tutorials May 15, 2026

[

### How to build a real-time AI chatbot in minutes with Netlify Agent Runners (no backend)

](/blog/how-to-build-a-real-time-ai-chatbot-in-minutes-with-netlify-agent-runners-no-backend)

-   ![Profile picture of Nahrin Jalal](/_astro/f0e7c8f227a03fe58340c99ef5439d5a896c0733-272x272_Z23kDpD.webp)
    
    Nahrin Jalal
    

![](/_astro/8fe9e8a23f944c9912003233d99a2df7fee637cf-1600x900_Z1gMhmf.webp)

Guides & Tutorials May 15, 2026

[

### Tracking AI search traffic: how to use Netlify Log Drains to maximize AEO

](/blog/tracking-ai-search-traffic)

-   ![Profile picture of Nahrin Jalal](/_astro/f0e7c8f227a03fe58340c99ef5439d5a896c0733-272x272_Z23kDpD.webp)
    
    Nahrin Jalal
    

## Recent posts

Tools & Services July 27, 2026

[

### The 13-year story of Netlify Drop

](/blog/thirteen-years-of-netlify-drop)

-   ![Profile picture of Wade Wegner](/_astro/0302ff22eb844e648b11d7cff3cedbbc3c9de876-2667x4000_Z5j6wM.webp)
    
    Wade Wegner
    

News & Announcements July 14, 2026

[

### More headroom, a lower per-credit rate, and a bill you can predict: introducing new Pro plan tiers

](/blog/new-pro-plan-tiers)

-   ![Profile picture of Gehrig Kunz](/_astro/b4e9f58d914d1334ea70d53ea55a1f26b26f1445-512x512_17SwOI.webp)
    
    Gehrig Kunz
    

News & Announcements July 13, 2026

[

### Netlify inside of Claude Design

](/blog/netlify-inside-of-claude-design)

-   ![Profile picture of Sean Roberts](/_astro/bbf2243f8171dbddd80ab2103622106cef84d125-512x512_Z1d2LKE.webp)
    
    Sean Roberts
    

![](/_astro/3f255b372fa958df35802666ee33b4609b2d71bd-1200x1586_1VtE2D.webp)

### How do the best dev and marketing teams work together?

[Access the report](https://www.netlify.com/reports/2024-leadership-trend-report/access/)