# Next + Hygraph

## Overview

[Next.js](https://nextjs.org/) is a React framework that you can use to create high-quality web applications powered by React components.

## Creating a new Next app

Start by initializing a new `Next.js 14` project. Open up your terminal, navigate to where you want your project, and run the following command:

```bash
npx create-next-app my-next-project

```

The interactive setup will ask you questions to configure your project. Initialize with the following answers:
- **Typescript:** No
- **ESLint:** Yes
- **Tailwind CSS:** Yes
- **src/ directory:** No
- **App Router:** Yes
- **Import alias:** No

After choosing the options, the CLI will install all the necessary pieces to run your `Next.js` site.

Once the installation completes, open the new Next project in a code editor of your choice.

You need to adjust the default Tailwind styling that `Next.js` gives us from the installation. To do this, remove the global CSS rules in `app/globals.css` except the following Tailwind imports:

```
@tailwind base;
@tailwind components;
@tailwind utilities;
```

Change directory to your new Next project run `npm install` to install dependencies:

```
cd my-next-project && npm install
```

Run the command  `npm run dev` to initialize the app. Your site will be available in the browser at `http://localhost:3000/`.

![Next](https://hygraph.com/images/docs/implementations/next/nextjs-locally.png)

### Configure Hygraph assets to work with Next

To work with Next image module, you need to specify Hygraph as an image domain by adding the domain URL in the `next.config.js` file.

Your config file should contain the following code:

```js
// next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {
  images: {
    dangerouslyAllowSVG: true,
    remotePatterns: [
      {
        protocol: 'https',
        hostname: '**.graphassets.com',
      },
     ]
    },
}
module.exports = nextConfig
```

## Getting data from Hygraph

Now that you have created your Next project, it's time to add some data from Hygraph. Start by cloning our demo Hygraph project:

[Click here to clone the demo project](https://app.hygraph.com/clone/751a6bdf9431476c8b82c543895e6d16?name=Implementation%20Guides)

After cloning, you will have a simple project that contains one content model called **Page** that contains fields for `Title`, `Slug`, and `Body`; and one content entry.

If you navigate to the Schema builder and click on the **Page** model, you will see this:

![Demo project - Page model](https://hygraph.com/images/docs/implementations/demo-project-page-model.png)

And if you navigate to the Content editor and view the sample entry details, you'll see this:

![Demo project - Sample content entry](https://hygraph.com/images/docs/implementations/demo-project-sample-entry.png)

## Content API

Before you can connect Next to Hygraph, you will need to configure **Content API** access permissions for unauthenticated requests.

To do this, we'll to go **Project settings > Access > API Access > Content API** in our Hygraph project, scroll to find the **Manage Content API access permissions** box and click `Initialize defaults`:

![Content API permissions](https://hygraph.com/images/docs/implementations/public-content-api-permissions.png)

Finally, we will copy the `High Performance Read-only Content API` endpoint from **Project settings > Access > API Access > Endpoints**. You will use it to connect Next to Hygraph later on.

## Testing a query in the API playground

Next, you should test if you can fetch the information in the sample content entry that we showed you earlier. To do this, navigate to the API Playground in your project and use the following query:

  **Query**

```graphql
query Page {
  page(where: {slug: "hygraph-works-with-any-framework"}) {
    title
    body {
      text
    }
  }
}
```

  
  **Response**

```json
{
  "data": {
    "page": {
      "title": "Hygraph works with any framework!",
      "body": {
        "text": "No matter the framework you choose, Hygraph is there for you and all your content needs. "
      }
    }
  }
}
```


If you execute the query, the response should fetch the sample query in the demo project you cloned.

Want to see Next and Hygraph in action? Watch a quick video on how to connect `Next` and `Hygraph`:
[Video](https://www.youtube.com/watch?v=fkSW0BFbtdo)

## Generating Hygraph content with Next

[After enabling API access](https://hygraph.com/docs/implementations/next/next#content-api), you can start using the **Pages** query with your Next app to render content.

Create an `.env` file in the root of your Next project. Add the endpoint URL you copied from Hygraph inside the `.env` file, like this:

```
NEXT_HYGRAPH_ENDPOINT=https://<HYGRAPH_CDN_LOCATION>.cdn.hygraph.com/content/<ID>/master
```
### Getting a list of pages for the homepage

After adding your `.env` file, go to your `page.js` file in the app directory and replace its contents with the following code:

  **JavaScript**
```js
// file: app/page.js
// get a list of pages from hygraph
import Link from "next/link";

async function getPages() {
  const NEXT_HYGRAPH_ENDPOINT = process.env.NEXT_HYGRAPH_ENDPOINT;
  const response = await fetch(NEXT_HYGRAPH_ENDPOINT, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      query: `query Pages {
                pages {
                  title
                  slug
                  body {
                    text
                  }
                }
              }`,
    }),
  });
  const json = await response.json();
  return json.data.pages;
}
export default async function Home() {
  const pages = await getPages();
  //console.log(pages);
  return (
    <div className="m-12">
      <h1 className="text-5xl font-bold mb-4">
        Hygraph Implementation Guides demo
      </h1>
      <p className="text-lg mb-4">Click the links below to see other pages</p>
      <ul className="mb-8 list-disc list-inside">
        {pages.map((page) => {
          return (
            <li key={page.slug}>
              <Link href={`/page/${page.slug}`} className="underline">
                {page.title}
              </Link>
            </li>
          );
        })}
      </ul>
      <p>
        <button
          className="bg-indigo-500 hover:bg-indigo-700 text-white font-bold py-2 px-4 my-2 rounded">
          <Link
            href="https://hygraph.com/docs/implementations"
            target="_blank">Implementation Docs</Link>
        </button>
      </p>
    </div>
  );
}
```
  
  **TypeScript**
```ts
// file: app/page.tsx
// get a list of pages from hygraph
import Link from "next/link";

async function getPages() {
  const response = await fetch(process.env.NEXT_HYGRAPH_ENDPOINT, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      query: `query Pages {
        pages {
          title
          slug
          body {
            text
          }
        }
      }`,
    }),
  });
  const json = await response.json();
  return json.data.pages;
}
export default async function Home() {
  const pages = await getPages();
  return (
    <div className="m-12">
      <h1 className="text-5xl font-bold mb-4">
        Hygraph Implementation Guides demo
      </h1>
      <p className="text-lg mb-4">Click the links below to see other pages</p>
      <ul className="mb-8 list-disc list-inside">
        {pages.map((page: any) => {
          return (
            <li key={page.slug}>
              <Link href={`/page/${page.slug}`} className="underline">
                {page.title}
              </Link>
            </li>
          );
        })}
      </ul>

      <p>
        <a
          className="bg-indigo-500 hover:bg-indigo-700 text-white font-bold py-2 px-4 my-6 rounded"
          href="https://hygraph.com/docs/implementations"
          target="_blank"
        >
          Implementation Docs
        </a>
      </p>
    </div>
  );
}
```


#### Code overview

In the above code, we have created the function `getPages()` that queries and fetches all pages from Hygraph. The `Home` function calls the `getPages` function and waits for the query to return with our content from Hygraph. Then, we use our content to  render a list of links to other pages and added a button that will bring you back to this guide.

![Homepage](https://hygraph.com/images/docs/implementations/next/next-homepage.png)

### Creating dynamic page routes with Next

Now, that we have a list of pages in our homepage, we need to create a dynamic route for each page. To do this, create a new directory in the `app` directory called `pages/[slug]` and a file called `page.js` inside the new directory. Once created add following code:

  **JavaScript**
```js
// file: app/page/[slug]/page.js
// get page content from hygraph and create a new page for each new slug
import Link from "next/link";
async function getPage(slug) {
    const NEXT_HYGRAPH_ENDPOINT = process.env.NEXT_HYGRAPH_ENDPOINT;
  const response = await fetch(NEXT_HYGRAPH_ENDPOINT, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      query: `query Page($slug:String!) {
        page(where: {slug: $slug}) {
          title
          slug
          body {
            text
          }
        }
      }`,
      variables: {
        slug,
      },
    }),
  });
  const json = await response.json();
  return json.data.page;
}
export default async function Page({ params }) {
  const page = await getPage(params.slug);
  return (
    <div className="m-12">
      <h1 className="text-5xl font-bold mb-4">{page.title}</h1>
      <p className="text-lg mb-8">{page.body.text}</p>

      <p>
        <Link href="/" className="underline">
          Back to homepage
        </Link>
      </p>
    </div>
  );
}
```

  **TypeScript**
```ts
// file: app/page/[slug]/page.tsx
// get page content from hygraph and create a new page for each new slug
import Link from "next/link";

async function getPage(slug: string) {
  const response = await fetch(process.env.NEXT_HYGRAPH_ENDPOINT, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      query: `query Page($slug:String!) {
        page(where: {slug: $slug}) {
          title
          slug
          body {
            text
          }
        }
      }`,
      variables: {
        slug,
      },
    }),
  });
  const json = await response.json();
  return json.data.page;
}

export default async function Page({ params }: { params: { slug: string } }) {
  const page = await getPage(params.slug);
  return (
    <div className="m-12">
      <h1 className="text-5xl font-bold mb-4">{page.title}</h1>
      <p className="text-lg mb-8">{page.body.text}</p>

      <p>
        <Link href="/" className="underline">
          Back to homepage
        </Link>
      </p>
    </div>
  );
}
```
  

#### Code overview

In the above code, we are taking advantage of the dynamic routing capabilities of the Next app router to create a page route,`http://localhost:3000/page/{page.slug}`, that makes new page for every `slug`. The `Page()` function calls the `getPage` function and waits for the query to return with our content from Hygraph. Then, we use our content to render the page title and body text, and added a button that will bring you back to the homepage.

![Dynamic page](https://hygraph.com/images/docs/implementations/next/next-dynamic-page.png)

Congratulations! You have a homepage and a dynamic page route to render all pages and their content.

**Pro Tip:**
This was a simple and quick example of how to fetch and render content from Hygraph using Next.

For more complete implementation examples, [clone a starter](https://app.hygraph.com/).
