This website uses cookies

Our website, platform and/or any sub domains use cookies to understand how you use our services, and to improve both your experience and our marketing relevance.

Sep 15, 2026 23:59:59

Limited-Time

Summer Offer

  • 0

    Days

  • 0

    Hours

  • 0

    Min

  • 0

    Sec

40% OFF

All Hosting Plans +
Unlimited Free Migrations

CLAIM NOW

*Valid till 15th September 2026

Next.js Headless CMS: What It Is and How to Build One

Updated on August 5, 2026

12 Min Read

Key Takeaways

  • A headless CMS keeps content separate, and Next.js turns it into fast static pages that load quickly and help SEO.
  • Since the CMS is separate from the frontend, there’s less exposure and you get full freedom over how the UI is built.
  • You don’t need a Node.js server for this setup, Next.js can output static files that run on any normal web server.

In a headless CMS, content is stored and managed separately from the frontend. A lot of modern blogs and eCommerce sites work this way. Content lives inside the CMS and gets sent to the frontend through an API.

Next.js works really well with headless setup because it can fetch content directly from the CMS and turn it into static pages. What this does is that it keeps the frontend fast and easier to manage compared to typical theme-based systems.

In this blog, I’ll cover why using Next.js with a headless CMS makes sense, and some of its benefits. Then I’ll build a small blog project that connects to Contentful to fetch the data and display articles locally.

Finally, I will show you how to push that project to GitHub and deploy it live on Cloudways Managed Node.js Hosting (Velocity). (Also, learn how to easily deploy a Node JS application on Cloudways)

Why Use Next.js with a Headless CMS?

One of the main reasons I believe any developer pairs Next.js with a headless CMS is due to performance. Next.js can generate pages ahead of time during the build process.

So…the site doesn’t have to request content over and over again from the CMS whenever someone visits a page.

This approach is called SSG (Static Site Generation).

Because pages are already built before the user opens the site, page loading time stays fast. And, the server has less work to handle. It also has SEO benefits since search engines like Google can read the content of the page directly from the HTML instead of waiting for JavaScript to load everything.

And lastly, we can’t forget about flexibility. CMS handles content management, while Next.js handles frontend separately. This makes both sides easier to work with.

Optimized Hosting for Headless CMS Setups

Build a powerful Headless CMS backend for your Next.js frontend. Cloudways delivers fast API response times, built-in caching, and reliable server performance.

How to Build a Headless Blog Using Next.js and Contentful

To show you how a Next.js headless CMS works in practice, I’ll create a mini project. It’ll basically be a modern, clean blog frontend that automatically fetches and displays articles written inside Contentful.

What I’ll Be Using

  • Node.js
  • VS Code
  • Contentful (Free tier)
  • Next.js and Tailwind CSS

Step 1: Setting Up the Headless CMS (Contentful)

First things first, I need a backend to store my blog posts. For this tutorial, I’ll be using the free tier of Contentful.

After I sign up, Contentful asks if I want to use a template. To save time, I chose the Blog template so I don’t have to build a database structure from scratch.

To check I have everything I need in Contentful, I’ll go to the Content model tab. I can see a few models already created.

Contentful dashboard panel showing custom content model types including Author, Rich image, and SEO components.

But I just need the page – Blog post one, which has 10 predefined fields like title, SEO properties, and content.

Contentful models schema panel highlighting a red box over the page blog post component list item.

Okay cool. Now I’ll go to the Content tab and again, since I used a template, Contentful should’ve already generated sample blog posts. I just need to check that the status is set to Published so the data can be fetched by my app.

Contentful entries dashboard showing a column list of articles with a green published status tag.

I can see the status as published so everything is good to go!

And one last thing I’ll do before I leave Contentful is copy my API keys so my Next.js app can talk to it.

To do this, I’ll go to Settings > API keys, click Add API key.

Then I’ll add a name and description so I remember what this key is for later. And click the Add API Key button to generate the keys.

Create API Key modal window with the key name set to nextjs headless cms.

I’ll leave this tab open so I can copy Space ID and the Content Delivery API – access token later.

Contentful web interface setting pane listing values for Space ID and Content Delivery API access tokens.

Step 2: Setting Up the Next.js Project

Now I’ll set up my Next.js frontend. But…before I create that, I need Node.js on my machine.

In my case, I’m using my office laptop which has IT restrictions so I’ll download the standalone binary version of Node.js from nodejs.org.

Node.js official download page with a red arrow pointing to the Standalone Binary zip button.

Once the download is complete, I’ll unzip the file in my downloads folder.

Windows file explorer downloads folder showing a zipped folder archive named node-v24.15.0-win-x64.zip.

Windows file explorer showing extracted Node.js files including node.exe and npm files.

Opening the project folder in Command Prompt

Now I’ll create a folder for my project. I’ll call it something simple like headless-blog.

Windows desktop wallpaper interface showing a standard yellow folder icon labeled headless-blog.

Next, I’ll open up command prompt where I’ll be running all my commands.

So the first command I’ll run would be to get to my project folder:

cd C:\Users\abdulrehman\Desktop\headless-blog

Pointing Command Prompt to the Node binary

Now…since the command prompt has no idea where Node is on my machine, I’ll run this command with the path where I unzipped my Node folder:

set PATH=%PATH%;C:\Users\abdulrehman\Downloads\node-v24.15.0-win-x64\node-v24.15.0-win-x64

To confirm everything is working correctly, I’ll run these two commands:

node -v
npm -v

I can see the version numbers for Node and npm, which means everything is in order.

Windows command prompt window displaying successful version outputs for node and npm.

Creating the Next.js project

I’ll now create my Next.js project by running:

npx create-next-app@latest .

The reason why I added the dot at the end of the command is to ensure Next.js sets up the project inside my current headless-blog folder and not in a new one.

I’ll accept the default prompt that pops up right after running the npx create-next-app@latest . command by hitting enter, making sure Tailwind CSS is selected. I’ll use it to create a clean UI for my project.

Command line console window displaying successful initialization text for creating a new headless-blog project folder.

Once Next.js finishes installing all the dependencies, it shows a Success! message.

Next I need the official packages to connect to Contentful and render its rich text. And to get them, I’ll run this installation command:

npm install contentful @contentful/rich-text-react-renderer

Command prompt showing the installation completion text for the contentful rich-text-react-renderer package.

Step 3: Fetching Data and Building a Clean UI

Next I’ll open up my project folder in VS Code. To do this, I’ll go to File > Open Folder and then select my project folder.

Visual Studio Code welcome panel alongside the active headless-blog workspace directory tree.

Securing the API Keys

Alright, I have my project opened in VS code, and now I need to store the Contentful keys I generated earlier in my actual project. To do this, in the root of my project folder, I’ll create a new file called .env.local and paste the keys inside the file:

CONTENTFUL_SPACE_ID=your_space_id_here
CONTENTFUL_ACCESS_TOKEN=your_access_token_here

Visual Studio Code code editor displaying environment variables for Contentful space ID and access token.

Setting up the Contentful Client

Next, I’ll set up the connection between my Next.js app and Contentful. To do this, in VS code, inside the app folder, I’ll create another folder and call it lib. And inside this new folder, a file called contentful.ts.

Visual Studio Code panel displaying the contentful.ts file configuration code structure.

In the contentful.ts file, I’ll paste this code to initialize the client:

import { createClient } from 'contentful';

export const client = createClient({
  space: process.env.CONTENTFUL_SPACE_ID as string,
  accessToken: process.env.CONTENTFUL_ACCESS_TOKEN as string,
});

Building the Blog UI

Now I’ll open the app/page.tsx file and delete the default Next.js code. I’ll replace it with my own code for which I’ll use some Tailwind CSS classes to give my blog UI a clean layout.

In the code I added my content type ID (pageBlogPost) which I found by going in the Content model tab, then opening the page – Blog post model, and clicking the Copy ID button.

Contentful schema builder dashboard screen showing content fields for a custom page blog post component model.

By adding the ID to the code, I’m telling Next.js which database table to pull data from, making sure it fetches my blog posts instead of author bios or landing pages.

import { client } from './lib/contentful';
import { documentToReactComponents } from '@contentful/rich-text-react-renderer';

export default async function Home() {
  // Fetch entries matching the template's exact ID
  const response = await client.getEntries({ content_type: 'pageBlogPost' });
  const posts = response.items;

  return (
    <main className="min-h-screen bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
      <div className="max-w-3xl mx-auto">
        <h1 className="text-4xl font-extrabold text-gray-900 mb-8 text-center">
          My Headless CMS Blog
        </h1>

        <div className="space-y-6">
          {posts.map((post: any) => (
            <article
              key={post.sys.id}
              className="bg-white p-6 rounded-lg shadow-sm border border-gray-100 hover:shadow-md transition-shadow"
            >
              <h2 className="text-2xl font-bold text-gray-800 mb-3">
                {post.fields.title}
              </h2>
              {/* Checking if there is content before rendering to prevent errors */}
              {post.fields.content && (
                <div className="text-gray-600 prose">
                  {documentToReactComponents(post.fields.content)}
                </div>
              )}
            </article>
          ))}
        </div>
      </div>
    </main>
  );
}

Visual Studio Code editor showing Next.js React code inside the page.tsx file layout.

Testing What We Built

Alright, time to test. I’m going to minimize VS code and hop back into command prompt and start the development server:

npm run dev

I’ll verify it started by opening my browser and going to http://localhost:3000.

Since I can see the exact sample posts that came with the Contentful template getting pulled and displayed in the UI I built, it means the headless connection is working perfectly.

The data is flowing from the backend (Contentful) directly into my frontend UI (Next.js).

Localhost browser window showing a web page titled Creating sustainable cities.

Step 4: Setting Up the Project for a Live Server

Since my project is working properly on local setup, I can deploy it on a live server. For this tutorial, I’ll use Cloudways.

If you also want to deploy on Cloudways, you can use the 3-day free trial we offer. Since I already have my server ready, I’ll just create a new PHP application.

Cloudways hosting panel applications list with a red arrow pointing to the Add Application button.

Application setup form with Custom App selected and name set to nextjs headless cms.

Once I have my PHP application ready on Cloudways, to make the Next.js project run properly on it, I’m not going to run a full Node.js backend on the server. Instead, I’m going to run a static export.

This way, Next.js generates regular static HTML files that can run on pretty much any web server.

To do this, I’ll open the next.config.ts in VS Code and add just one line inside the configuration block: output: ‘export’.

Like this:

import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  output: 'export',
};

export default nextConfig;'

Visual Studio Code panel pointing to a red arrow highlighting the output export line inside next.config.ts.

After saving the file, I’ll go back to the command prompt and stop the dev server. I’ll hit CTRL+C to stop it.

And then I’ll run the build command:

npm run build

While the command runs, Next.js will start to pull all the sample blog posts from Contentful and convert them into static HTML files. And once that is done, there’ll be a new out folder in my project.

Terminal command window showing a successful Next.js production build compilation output.

And if I check VS code now, I can see the out folder created.

Visual Studio Code file explorer view highlighting the static build directory named out.

This is the folder with the final site ready that I’ll upload onto my Cloudways Node JS hosting server.

Step 5: Pushing the Project to GitHub

Before I can push my code to Git, I’ll go to GitHub and create a repository.

GitHub repository creation page showing the repository name field filled with nextjs headless cms.

Once the repo ready, I’ll go back to command prompt and run these commands one at a time to upload my project to Git:

git init
git add .
git commit -m "First commit with static export"
git branch -M main
git remote add origin https://github.com/abdulrehman293/nextjs-headless-cms
git push -u origin main

Now I’ll go back to my GitHub repo and refresh. And as expected, all my files and folders are uploaded to my repo.

GitHub repo page for 'nextjs-headless-cms' showing file tree with folders (app, out, public) and top commit activity in a dark theme.

Step 6: Deploying to Cloudways Managed Node.js Hosting

Now that everything is working perfectly on my local setup and the code is safely on GitHub, I’m going to take this headless blog live. I’ll deploy it on Cloudways Managed Node.js Hosting (Velocity).

Launching the app on Cloudways

I’ll head over to my Cloudways dashboard to create a new Node.js application. I’ll click on Velocity from the left-side menu and hit Get Started.

Velocity by Cloudways

 

Then I’ll just pick the Starter plan and click Proceed.

Choose the starter plan for Node JS

Connecting my GitHub repository

Next, I need to link up my code. Cloudways gives options to connect to GitHub, GitLab, or Bitbucket.

Verify Github
Since my project is on GitHub, I’ll connect to that.
Once my account is connected, I’ll pick my nextjs-headless-cms repo from the dropdown and click Continue.
Folder list with 'nextjs-headless-cms' selected; Continue button and $22.50 monthly price at bottom.
After that, Cloudways will automatically figure out the settings for my app. In my case, it picked the framework as Next.js CSR, the branch as main, and the node version as Node 24 (LTS).

Reveiw build settings

I didn’t have to configure these settings manually.

Adding the Contentful API keys

Before I actually deploy, there’s one important step. My app needs the Contentful API keys to fetch the blog posts. Locally, I stored them in my .env.local file, and didn’t push it to GitHub for security reasons. So now I’ll add them to Cloudways.

I’ll go to the Environment Variables section, click Add, and paste my keys exactly as I did in the env file:

  • CONTENTFUL_SPACE_ID : your_space_id_here
  • CONTENTFUL_ACCESS_TOKEN : your_access_token_here

Modal titled Set environment variables with two variables: CONTENTFUL_SPACE_ID and CONTENTFUL_ACCESS_TOKEN, including value fields and a warning about sensitive data.

What this’ll do is ensure that my live app can securely talk to my Contentful space to get the data.

Deploying the app

With the environment variables added, I will hit Save, and then click Deploy Now.

Deployment settings screen for a GitHub project; shows repository name nextjs-headless-cms, framework Next.js CSR, branch main, Node version v24, root directory ./, and a blue Deploy Now button.

Cloudways will start pulling the code from my GitHub, install all the npm dependencies, run the build command, and start the server.

Deployment steps screen titled 'Deploying your Node.js app' with a 'Deployment settings' dropdown; a card shows 'Setting Up Your Velocity Server' with descriptive text and a progress circle, and a disabled step 'Building your application'.

Checking the live blog

Once the deployment finishes up, I can access the temporary Cloudways URL from my app’s Overview page in the dashboard.

Deployment successful screen showing setup steps for Velocity Server and app build, with a Build Logs warning and a 'Go to Application Listing' button.

Dashboard screenshot of nextjs-headless-cms with left navigation and main panels showing deployment, domain, and plan details, including a temporary domain notice.

And that’s it! Now if I click my Application URL, the site is live on Cloudways, displaying the exact same sample posts we fetched from Contentful earlier on the local setup.

Web browser window displaying a published blog post article titled Creating sustainable cities and the role of green urbanism.

Wrapping Up

That wraps up our guide on Next.js headless CMS. In this blog, I tried to cover exactly why this stack makes sense and the performance/security benefits you can get by separating your backend from the frontend.

I showed you how to build a Next.js frontend that automatically pulls data from Contentful on a local setup. After that, I pushed the working project to my GitHub and deployed it live using Cloudways Managed Node.js Hosting (Velocity).

The full project is available on my GitHub. Feel free to clone it and use the code as a starting point for your own headless blog. If you have any questions about the setup or the deployment process, just let me know in the comments.

Q. Is Next.js headless?

No, Next.js is a frontend framework. It is not a CMS. It is however used commonly with headless CMS platforms like Contentful or Sanity to display content on the frontend.

Q. What is the best headless CMS for Next.js?

This depends on your project. Contentful is easy to start with. Sanity gives you a bit more flexibility. Strapi is best if you want to host the CMS yourself.

Q. Does a headless CMS help with SEO?

Yes it does. A headless CMS stores the content, while Next.js renders the content into fast-loading pages that search engines can crawl more easily. So the easier the page to crawl, this can indirectly benefit your site’s SEO.

Q. Do I need a Node.js server to host Next.js?

Not always. If the project uses SSR or API routes, you’ll require Node.js. But for static exports, generated files can be hosted on a regular web server without running Node.js.

Share your opinion in the comment section. COMMENT NOW

Share This Article

Abdul Rehman

Abdul is a tech-savvy, coffee-fueled, and creatively driven marketer who loves keeping up with the latest software updates and tech gadgets. He's also a skilled technical writer who can explain complex concepts simply for a broad audience. Abdul enjoys sharing his knowledge of the Cloud industry through user manuals, documentation, and blog posts.

×

Webinar: How to Get 100% Scores on Core Web Vitals

Join Joe Williams & Aleksandar Savkovic on 29th of March, 2021.

Do you like what you read?

Get the Latest Updates

Share Your Feedback

Please insert Content

Thank you for your feedback!

Do you like what you read?

Get the Latest Updates

Share Your Feedback

Please insert Content

Thank you for your feedback!

Want to Experience the Cloudways Platform in Its Full Glory?

Take a FREE guided tour of Cloudways and see for yourself how easily you can manage your server & apps on the leading cloud-hosting platform.

Start my tour