What are the main steps to convert a Hygraph Next.js project to the Next.js app directory beta?
The main steps include: 1) Upgrading your Next.js dependency to version 13 or higher, 2) Enabling the experimental app directory feature in next.config.js by setting experimental: { appDir: true }, 3) Creating an app directory inside src, 4) Incrementally moving routes from /pages to /app, 5) Creating a root layout component (RootLayout), 6) Renaming index.js to page.js in the app directory, and 7) Refactoring dynamic routes to the new directory structure. Note: Both /pages and /app can coexist during migration, but API routes and some static routes may still require the /pages directory. Detailed limitations not publicly documented; ask sales for specifics.
What are the key differences between the /pages and /app directory structures in Next.js 13?
The /app directory introduces React Server Components, allowing business logic to run on the server and reducing the amount of JavaScript sent to the client. It also enables colocated files for error handling, loading states, and metadata (e.g., error.jsx, loading.jsx, head.jsx). The /pages directory relies on conventions like getStaticProps and getStaticPaths, while the /app directory uses async functions and the params object for data fetching. Note: Some legacy features and API routes may still require the /pages directory. Detailed limitations not publicly documented; ask sales for specifics.
What prerequisites are needed to migrate a Hygraph project to the Next.js app directory beta?
You should have a basic understanding of Next.js, GraphQL, and Hygraph. Experience with React and familiarity with the Next.js 13+ features, such as React Server Components and the new data fetching model, are also recommended. Note: The migration process assumes comfort with updating dependencies and refactoring code. Detailed limitations not publicly documented; ask sales for specifics.
How does data fetching change when using the Next.js app directory with Hygraph?
In the app directory, you use async functions and the fetch API directly within your server components. Next.js adds caching and deduplication, so identical fetch requests are only made once, even if called in multiple places. This differs from the /pages directory, which uses getStaticProps and getStaticPaths. Note: Some advanced data fetching patterns may require additional configuration. Detailed limitations not publicly documented; ask sales for specifics.
What are common pitfalls or errors when migrating to the app directory structure?
Common issues include: 1) Conflicting routes between /pages and /app (e.g., duplicate index.js and page.js), 2) Outdated usage of the Link component (no longer requires an <a> tag inside), 3) Missing root layout component, and 4) Not handling 404s properly with the new not-found.jsx pattern. Note: Some legacy features and static API routes may not be fully supported in the app directory. Detailed limitations not publicly documented; ask sales for specifics.
How do you implement custom 404 pages in the Next.js app directory with Hygraph?
Add a not-found.jsx file in the relevant route directory (e.g., /app/products/[slug]/not-found.jsx). In your page component, check if the fetched data is undefined and call the notFound() function from next/navigation. This will render the custom 404 page and add a noindex meta tag for SEO. Note: Proper error handling is essential to avoid unhandled exceptions. Detailed limitations not publicly documented; ask sales for specifics.
Features & Capabilities
What APIs does Hygraph provide for integration with Next.js projects?
Hygraph offers several APIs: 1) GraphQL Content API for querying and manipulating content, 2) Management API for handling project structure, 3) Asset Upload API for uploading files, and 4) MCP Server API for secure communication with AI assistants. For more details, see the API Reference documentation. Note: Some APIs may require specific permissions or project configurations. Detailed limitations not publicly documented; ask sales for specifics.
What integrations are available for Hygraph projects?
Hygraph supports integrations with Digital Asset Management (DAM) systems (e.g., Aprimo, AWS S3, Bynder, Cloudinary, Imgix, Mux, Scaleflex Filerobot), hosting and deployment platforms (Netlify, Vercel), Product Information Management (Akeneo), commerce solutions (BigCommerce), and translation/localization tools (EasyTranslate). For a full list, visit the Hygraph Marketplace. Note: Integration availability may depend on your plan and project setup. Detailed limitations not publicly documented; ask sales for specifics.
Performance & Implementation
How does Hygraph optimize performance for content delivery in Next.js projects?
Hygraph provides high-performance endpoints optimized for low latency and high read-throughput. A read-only cache endpoint delivers 3-5x latency improvement. The platform actively measures GraphQL API performance and offers practical advice for optimization. For more, see the performance improvements blog post and the GraphQL Report 2024. Note: Actual performance may vary based on project complexity and configuration. Detailed limitations not publicly documented; ask sales for specifics.
How long does it take to implement Hygraph in a Next.js project?
Implementation time varies by project complexity. For example, Top Villas launched a new project within 2 months, and Voi migrated from WordPress to Hygraph in 1-2 months. Starter projects, structured onboarding, and extensive documentation help accelerate adoption. Note: Large-scale or highly customized projects may require additional time. Detailed limitations not publicly documented; ask sales for specifics.
Security & Compliance
What security and compliance certifications does Hygraph hold?
Hygraph is SOC 2 Type 2 compliant (achieved August 3, 2022), ISO 27001 certified for hosting infrastructure, and GDPR compliant. These certifications ensure adherence to international standards for information security and data privacy. For more, visit the Secure Features page. Note: Certification scope may vary by deployment and region. Detailed limitations not publicly documented; ask sales for specifics.
Use Cases & Success Stories
What types of companies and roles benefit from using Hygraph with Next.js?
Hygraph is used by developers, content creators, product managers, and marketing professionals in enterprises and high-growth companies. Industries include SaaS, eCommerce, media, healthcare, automotive, and more. Notable customers include Samsung, Dr. Oetker, Komax, AutoWeb, BioCentury, Voi, HolidayCheck, and Lindex Group. For more, see Hygraph's case studies. Note: Smaller teams or projects with minimal content management needs may find simpler solutions sufficient. Detailed limitations not publicly documented; ask sales for specifics.
Can you share examples of business impact from using Hygraph with Next.js?
Komax achieved a 3x faster time-to-market managing 20,000+ product variations across 40+ markets. Samsung improved customer engagement by 15%. AutoWeb saw a 20% increase in website monetization. Voi scaled multilingual content across 12 countries and 10 languages. For more, see Hygraph's case studies. Note: Results may vary based on implementation and business context. Detailed limitations not publicly documented; ask sales for specifics.
Support & Documentation
What documentation and resources are available for migrating Hygraph projects to Next.js app directory?
Key resources include the API Reference documentation, Getting Started guides, and integration guides for platforms like Mux and Akeneo. Community support is available via Slack, and training resources include webinars and live streams. Note: Some advanced migration scenarios may require direct support. Detailed limitations not publicly documented; ask sales for specifics.
Convert a Hygraph Next.js project to Next.js app directory beta
In this article, we're going to take a look at the new app structure and convert an existing Hygraph project to this new structure. We'll take this step by step and see how incremental adoption really works.
Last updated by Bryan
on Jan 21, 2026
Originally written by Bryan
In late 2022, the Next.js team launched their next stable version: Next.js 13. While this update came with a lot of improved functionality, one new feature is set to redefine the way you build with Next: the app directory beta.
The app beta is not used default. It needs to be enabled and can then be incrementally adopted. In this article, we're going to take a look at the new app structure and convert an existing Hygraph project to this new structure. We'll take this step by step and see how incremental adoption really works.
The new app directory structure isn’t just a reorganization of your project (though it is, and that reorganization feels powerful). This new methodology utilizes React Server Components to bring many new features and mental models. With Server components, a developer can do their business logic in a React component that doesn’t need to be sent to the client. This allows for a lot less JavaScript to be sent to the browser. If you have frontend needs, you can then use client components that get sent individually to the browser. This should reduce your bundle size down to a more manageable state. Just the code you need for interactivity.
The overall data fetching model has shifted, as well. Next has extended the native fetch() method from Node and the browser APIs and has added additional caching and deduplication functionality. This means you can create requests for data in various files, but the request will only fire to your API once. Fetching your blog posts to create a list on your homepage and to create the blog page list? Now that’s 1 API request, despite writing the code in multiple places. This gives a lot of developer convenience while creating better build and serve times.
There are even more new and improved features, but to use them, we need to be able to upgrade our project to use this new structure. It’s not as simple as moving your page files into the app directory, so let’s dig in and get things updated.
#Setting up a Next.js 13 project to work with the app directory
To start, we need a Next.js project. While this process is possible with any Next project using data fetching, let’s start from our simple Next example from the hygraph-examples GitHub repository. Run the following commands:
Before we install, we’ll need to update some dependencies in the package.json file. Let’s upgrade Next to ^13.0.0 and remove the react and react-doc dependencies.
Your package.json should now look like this:
{
"name":"hygraph-with-nextjs",
"private":true,
"license":"MIT",
"scripts":{
"dev":"next",
"build":"next build",
"start":"next start"
},
"dependencies":{
"graphql-request":"^1.8.2",
"next":"^13.0.0"
}
}
Now we can start the development server by running npm run dev. Immediately on loading the local version, we’re presented with the first update. Since this was previously not running Next 13, the Link component is structured wrong. In Next 13, we no longer need to have an anchor tag inside the Link component. This is a great update, but we need to change these references. The only location the Link component is used is the homepage in /src/pages/index.js. Open that file, and remove the <a></a> tags to get the site to run
// Old
<Link key={slug} href={`/products/${slug}`}>
<a>{name}</a>
</Link>
// New
<Link key={slug} href={`/products/${slug}`}>
{name}
</Link>
Now that the site runs, let’s update from the Pages directory to the new app directory.
Before we can convert to the app directory, we need to let Next know that we’ll be using this experimental feature. To do that, we need a configuration file. In the root of our project, let’s create a next.config.js file. Inside that file, add the following basic configuration.
/** @type {import('next').NextConfig} */
const nextConfig ={
experimental:{
appDir:true,
},
};
module.exports= nextConfig;
From there, we can create our app directory. Inside the src directory, add an app directory. We’ll be moving each of our routes to this directory. The nice thing is that each of our older routes will continue to work as we make these changes, since both directories can work at the same time.
Creating the root layout component
One of the first big changes to the overall structure is the need of a “root layout.” This will be the scaffolding of Markup for all pages. This can start very simply, but have any global information that each route will need. The RootLayout function accepts a children object. That children object will contain the Server Components that we’ll add via each page we create.
exportdefaultfunctionRootLayout({children}){
return(
<html lang="en">
<body>
{ children }
</body>
</html>
)
}
With this layout, we can now add our first page.
Adding the homepage
Instead of the index.js convention of the /pages directory, each page in the app directory will be named page.js. In the root of the app directory, create a new page.js file. This will be our homepage.
Once you create this page, Next will thrown an error in the console. There is now a conflicting route: /src/pages/index.js is the same route as /src/app/page.jsx. For now, rename /src/pages/index.js to oldIndex.js. We’ll delete this file later, but this file is the blueprint for our new file.
Once we rename the file, we get a new error. The page.jsx file is not exporting a React component. In fact, it’s exporting anything, since it’s blank. Let’s fix that and export a simple React component with an h1 of Products.
exportdefaultasyncfunctionPage(){
return(
<>
<h1>Products</h1>
</>
)
}
Now the homepage should have the H1 instead of the product list from the old homepage. Let’s get the list of products back.
In the old index file, we export a function called getStaticProps to get and pass the data to our page component. In the new structure, we don’t need to export anything or name things in any specific ways. Instead, we can create a regular async function to fetch our data.
Before our Server Component in the new page.jsx file, create a new async function named getProducts. This run a fetch request to the Hygraph endpoint for the project and return the products array. We can then run that function in our Server Component to loop through the data and display a link to each page.
A few things have changed between our old version and new.
Since we’re not using getStaticProps, we no longer need to structure our return in a specific way. Instead, we just return back the array of products
Using fetch instead of GraphQLRequest. By using fetch, we allow Next to cache the information and if we execute an identical fetch later, it won’t make a separate call, but instead use this data
Once you save this in, we have a functioning homepage. These links even take us to the pages associated with our old dynamic routes — since /app and /pages can work incrementally. That could be a fine stopping point, but let’s convert our dynamic route over, as well.
Converting the dynamic products route
Just like the homepage, we’ll start by setting up our structure. Instead of the dynamic route brackets happening on the file, hey happen on the directory. So the /pages/products[slug].js will change to be /app/products/[slug]/page.jsx. This allows for more flexibility and the ability to add custom, co-located features such as error pages, loading pages, and custom layouts.
Create the new file and add a simple component like we did for the homepage.
exportdefaultasyncfunctionPage(){
return(
<>
<h1>This is a product</h1>
</>
)
}
This time, the application won’t immediately error, since the static pages aren’t being rebuilt, but if you restart Next, it will throw the same error as before about conflicting files. Delete or rename the file and we’ll move forward.
The overall structure of this file is significantly different. Just like the homepage, we no longer need the getStaticProps function, but we also don’t need the getStaticPaths either. These are all files that render on the server, so we can move all that information into a single async function that can happen at request time.
The new Server Component gives us a params object that we can use to get the slug for the current route. We can pass that into a new getProduct() function and use that as a variable in our query to Hygraph. This will fetch the data for that specific product. We can then use that in the Markup generated by our component to display the title, description, and price.
We now have all the pages working together. Let’s take this one step further and add a custom 404 page for any products that aren’t found.
Setting up a custom 404 page
Because of the new app structure, we can colocate all of our relative files. In this case, if we want a custom 404 page, we can add a not-found.jsx template in the /products/[slug] directory.
The file will export a Server (or client) component, and for now, we’ll have a very simple message. In this case, since we’re looking for a product, let’s be specific and say “Product not found” instead of a simple “Page not found.”
Instead of getting a 404 page, we receive an unhandled error. That’s because we need to tell Next when we know it’s not found. In this case, if our query to Hygraph returns no results, we need to throw a 404.
After calling the getProduct() function, we can check if product is defined and if not, run the notFound() function from next/navigation. This will do a few things for us. It will redirect the browser to the NotFound component and automatically add a "noindex" meta tag to these routes. This is good SEO practice and will keep your site’s 404 pages from being indexed by search engines.
exportdefaultasyncfunctionPage({params}){
const product =awaitgetProduct(params)
if(!product)notFound()
return(
<>
<h1>{product.name}</h1>
<p>{product.description}</p>
<p>{product.price}</p>
</>
)
}
Now, we have a fully-functioning 404 page!
From here, you can delete the /pages directory and move to working on your app. You’ll still use the pages directory for your API routes, as well as any static routes you want to use, but most things can be used to this new, more-powerful version of Next.
With that, we have fully converted our simple Hygraph Next.js example from /pages to /app. At this point, I’d suggest taking look at all the different file types you can create in the colocated directories.
Add a head.jsx file to specify meta data such as title, description, and more for each product page
Add a loading.jsx file for loading page for longer queries.
Add an error.jsx file to handle other error types.
Blog Author
Bryan Robinson
Head of Developer Relations
Bryan is Hygraph's Head of Developer Relations. He has a strong passion for developer education and experience as well as decoupled architectures, frontend development, and clean design.
Share with others
Sign up for our newsletter!
Be the first to know about releases and industry news and insights.
Convert a Hygraph Next.js project to Next.js app directory beta
In this article, we're going to take a look at the new app structure and convert an existing Hygraph project to this new structure. We'll take this step by step and see how incremental adoption really works.
Last updated by Bryan
on Jan 21, 2026
Originally written by Bryan
In late 2022, the Next.js team launched their next stable version: Next.js 13. While this update came with a lot of improved functionality, one new feature is set to redefine the way you build with Next: the app directory beta.
The app beta is not used default. It needs to be enabled and can then be incrementally adopted. In this article, we're going to take a look at the new app structure and convert an existing Hygraph project to this new structure. We'll take this step by step and see how incremental adoption really works.
The new app directory structure isn’t just a reorganization of your project (though it is, and that reorganization feels powerful). This new methodology utilizes React Server Components to bring many new features and mental models. With Server components, a developer can do their business logic in a React component that doesn’t need to be sent to the client. This allows for a lot less JavaScript to be sent to the browser. If you have frontend needs, you can then use client components that get sent individually to the browser. This should reduce your bundle size down to a more manageable state. Just the code you need for interactivity.
The overall data fetching model has shifted, as well. Next has extended the native fetch() method from Node and the browser APIs and has added additional caching and deduplication functionality. This means you can create requests for data in various files, but the request will only fire to your API once. Fetching your blog posts to create a list on your homepage and to create the blog page list? Now that’s 1 API request, despite writing the code in multiple places. This gives a lot of developer convenience while creating better build and serve times.
There are even more new and improved features, but to use them, we need to be able to upgrade our project to use this new structure. It’s not as simple as moving your page files into the app directory, so let’s dig in and get things updated.
#Setting up a Next.js 13 project to work with the app directory
To start, we need a Next.js project. While this process is possible with any Next project using data fetching, let’s start from our simple Next example from the hygraph-examples GitHub repository. Run the following commands:
Before we install, we’ll need to update some dependencies in the package.json file. Let’s upgrade Next to ^13.0.0 and remove the react and react-doc dependencies.
Your package.json should now look like this:
{
"name":"hygraph-with-nextjs",
"private":true,
"license":"MIT",
"scripts":{
"dev":"next",
"build":"next build",
"start":"next start"
},
"dependencies":{
"graphql-request":"^1.8.2",
"next":"^13.0.0"
}
}
Now we can start the development server by running npm run dev. Immediately on loading the local version, we’re presented with the first update. Since this was previously not running Next 13, the Link component is structured wrong. In Next 13, we no longer need to have an anchor tag inside the Link component. This is a great update, but we need to change these references. The only location the Link component is used is the homepage in /src/pages/index.js. Open that file, and remove the <a></a> tags to get the site to run
// Old
<Link key={slug} href={`/products/${slug}`}>
<a>{name}</a>
</Link>
// New
<Link key={slug} href={`/products/${slug}`}>
{name}
</Link>
Now that the site runs, let’s update from the Pages directory to the new app directory.
Before we can convert to the app directory, we need to let Next know that we’ll be using this experimental feature. To do that, we need a configuration file. In the root of our project, let’s create a next.config.js file. Inside that file, add the following basic configuration.
/** @type {import('next').NextConfig} */
const nextConfig ={
experimental:{
appDir:true,
},
};
module.exports= nextConfig;
From there, we can create our app directory. Inside the src directory, add an app directory. We’ll be moving each of our routes to this directory. The nice thing is that each of our older routes will continue to work as we make these changes, since both directories can work at the same time.
Creating the root layout component
One of the first big changes to the overall structure is the need of a “root layout.” This will be the scaffolding of Markup for all pages. This can start very simply, but have any global information that each route will need. The RootLayout function accepts a children object. That children object will contain the Server Components that we’ll add via each page we create.
exportdefaultfunctionRootLayout({children}){
return(
<html lang="en">
<body>
{ children }
</body>
</html>
)
}
With this layout, we can now add our first page.
Adding the homepage
Instead of the index.js convention of the /pages directory, each page in the app directory will be named page.js. In the root of the app directory, create a new page.js file. This will be our homepage.
Once you create this page, Next will thrown an error in the console. There is now a conflicting route: /src/pages/index.js is the same route as /src/app/page.jsx. For now, rename /src/pages/index.js to oldIndex.js. We’ll delete this file later, but this file is the blueprint for our new file.
Once we rename the file, we get a new error. The page.jsx file is not exporting a React component. In fact, it’s exporting anything, since it’s blank. Let’s fix that and export a simple React component with an h1 of Products.
exportdefaultasyncfunctionPage(){
return(
<>
<h1>Products</h1>
</>
)
}
Now the homepage should have the H1 instead of the product list from the old homepage. Let’s get the list of products back.
In the old index file, we export a function called getStaticProps to get and pass the data to our page component. In the new structure, we don’t need to export anything or name things in any specific ways. Instead, we can create a regular async function to fetch our data.
Before our Server Component in the new page.jsx file, create a new async function named getProducts. This run a fetch request to the Hygraph endpoint for the project and return the products array. We can then run that function in our Server Component to loop through the data and display a link to each page.
A few things have changed between our old version and new.
Since we’re not using getStaticProps, we no longer need to structure our return in a specific way. Instead, we just return back the array of products
Using fetch instead of GraphQLRequest. By using fetch, we allow Next to cache the information and if we execute an identical fetch later, it won’t make a separate call, but instead use this data
Once you save this in, we have a functioning homepage. These links even take us to the pages associated with our old dynamic routes — since /app and /pages can work incrementally. That could be a fine stopping point, but let’s convert our dynamic route over, as well.
Converting the dynamic products route
Just like the homepage, we’ll start by setting up our structure. Instead of the dynamic route brackets happening on the file, hey happen on the directory. So the /pages/products[slug].js will change to be /app/products/[slug]/page.jsx. This allows for more flexibility and the ability to add custom, co-located features such as error pages, loading pages, and custom layouts.
Create the new file and add a simple component like we did for the homepage.
exportdefaultasyncfunctionPage(){
return(
<>
<h1>This is a product</h1>
</>
)
}
This time, the application won’t immediately error, since the static pages aren’t being rebuilt, but if you restart Next, it will throw the same error as before about conflicting files. Delete or rename the file and we’ll move forward.
The overall structure of this file is significantly different. Just like the homepage, we no longer need the getStaticProps function, but we also don’t need the getStaticPaths either. These are all files that render on the server, so we can move all that information into a single async function that can happen at request time.
The new Server Component gives us a params object that we can use to get the slug for the current route. We can pass that into a new getProduct() function and use that as a variable in our query to Hygraph. This will fetch the data for that specific product. We can then use that in the Markup generated by our component to display the title, description, and price.
We now have all the pages working together. Let’s take this one step further and add a custom 404 page for any products that aren’t found.
Setting up a custom 404 page
Because of the new app structure, we can colocate all of our relative files. In this case, if we want a custom 404 page, we can add a not-found.jsx template in the /products/[slug] directory.
The file will export a Server (or client) component, and for now, we’ll have a very simple message. In this case, since we’re looking for a product, let’s be specific and say “Product not found” instead of a simple “Page not found.”
Instead of getting a 404 page, we receive an unhandled error. That’s because we need to tell Next when we know it’s not found. In this case, if our query to Hygraph returns no results, we need to throw a 404.
After calling the getProduct() function, we can check if product is defined and if not, run the notFound() function from next/navigation. This will do a few things for us. It will redirect the browser to the NotFound component and automatically add a "noindex" meta tag to these routes. This is good SEO practice and will keep your site’s 404 pages from being indexed by search engines.
exportdefaultasyncfunctionPage({params}){
const product =awaitgetProduct(params)
if(!product)notFound()
return(
<>
<h1>{product.name}</h1>
<p>{product.description}</p>
<p>{product.price}</p>
</>
)
}
Now, we have a fully-functioning 404 page!
From here, you can delete the /pages directory and move to working on your app. You’ll still use the pages directory for your API routes, as well as any static routes you want to use, but most things can be used to this new, more-powerful version of Next.
With that, we have fully converted our simple Hygraph Next.js example from /pages to /app. At this point, I’d suggest taking look at all the different file types you can create in the colocated directories.
Add a head.jsx file to specify meta data such as title, description, and more for each product page
Add a loading.jsx file for loading page for longer queries.
Add an error.jsx file to handle other error types.
Blog Author
Bryan Robinson
Head of Developer Relations
Bryan is Hygraph's Head of Developer Relations. He has a strong passion for developer education and experience as well as decoupled architectures, frontend development, and clean design.
Share with others
Sign up for our newsletter!
Be the first to know about releases and industry news and insights.