

In today's digital landscape, creating dynamic websites is more important than ever. This guide will walk you through the process of building dynamic websites using Payload NextJS. We will cover how to set up Tailwind CSS, create a pages collection, and implement a header and footer for your website. This tutorial is based on insights from the AllAboutPayload YouTube channel, which provides valuable resources for developers interested in Payload and NextJS.
This article provides a detailed written step-by-step tutorial based on our comprehensive video guide available on YouTube at https://www.youtube.com/watch?v=8BXT64lnTXc. For visual learners or those who prefer following along with video instruction, the YouTube tutorial covers the same content while offering additional context and real-time demonstrations of each implementation step in the process.
Before diving into the implementation, let's briefly discuss the backend structure of our project. The project consists of several collections, primarily focusing on user management and media storage.
In addition to the pages, we will have a global header and footer that will be consistent across all pages. This keeps our design uniform and allows for easy updates in the future.

To enhance the styling of our website, we will be using Tailwind CSS. The first step is to create a root layout where we can import our Tailwind CSS styles. This layout will be essential for both the frontend and the Payload backend.
layout.tsx in your app directory.After setting up the layout, we will install the necessary dependencies for Tailwind CSS. Using pnpm, run the command to install the packages:
pnpm install -D tailwindcss postcss autoprefixer
Next, initialize Tailwind CSS:
pnpx tailwindcss init -p
This command will create two configuration files: tailwind.config.js and postcss.config.js. Now, we need to specify the content sources in the Tailwind config file:
content: ['./app/**/*.{js,ts,jsx,tsx}']
Finally, create a global CSS file to include Tailwind's layers and import it in your layout:
import './styles/globals.css'
Now that we have Tailwind CSS set up, the next step is to create a pages collection. This will allow us to manage the content dynamically.
To create the pages collection:
pages.ts in your collections directory.export const pages = {
slug: 'pages',
fields: [
{
name: 'name',
type: 'text',
required: true,
},
{
name: 'slug',
type: 'text',
required: true,
admin: {
position: 'sidebar',
},
},
{
name: 'layout',
type: 'blocks',
blocks: [],
},
],
};
With this setup, each page will have a unique name and slug. The layout will be an array of blocks, which we will define later.
Next, we will implement a global header and footer for our website. This will involve creating schemas for both components.
globals in your project.header.ts and footer.ts files in the globals directory.In header.ts, define the schema as follows:
export const header = {
slug: 'header',
fields: [
{
name: 'logo',
type: 'upload',
relationTo: 'media',
required: true,
},
{
name: 'nav',
type: 'array',
required: true,
minRows: 1,
fields: [
{
name: 'label',
type: 'text',
},
{
name: 'link',
type: 'text',
},
],
},
],
};
In footer.ts, define a similar schema, but include a copyright notice:
export const footer = {
slug: 'footer',
fields: [
{
name: 'logo',
type: 'upload',
relationTo: 'media',
required: true,
},
{
name: 'copyright',
type: 'text',
required: true,
},
],
};
Now that we have our header and footer set up, the next step is to render our pages in the frontend. This will involve creating dynamic routes.
In your website folder, create another folder named [slug] and inside it, create a page.tsx file. This file will handle the dynamic routing based on the slug provided.
Add the following code to page.tsx:
import { useRouter } from 'next/router';
const Page = () => {
const router = useRouter();
const { slug } = router.query;
// Fetch the page data using the slug here
return (
{/* Render the page content here */}
);
};
export default Page;
To provide more flexibility in our layouts, we will create block schemas for different types of content. These include a cover block, a rich text block, and an image block.
blocks in your project.cover.tsrichText.tsimage.tsDefine the cover block schema:
export const cover = {
slug: 'cover',
fields: [
{
name: 'title',
type: 'text',
required: true,
},
{
name: 'subtitle',
type: 'text',
required: true,
},
],
};Define the rich text block schema:
export const richText = {
slug: 'richText',
fields: [
{
name: 'content',
type: 'richText',
required: true,
},
],
};Define the image block schema:
export const image = {
slug: 'image',
fields: [
{
name: 'image',
type: 'upload',
relationTo: 'media',
required: true,
},
],
};With everything set up, the final step is to deploy your project to Vercel. This process is straightforward:
Make sure to test your deployed site to verify everything is functioning as expected.
Payload is a headless CMS built with Node.js, offering flexibility and a powerful admin panel for managing content.
NextJS is a React framework that enables server-side rendering and static site generation, enhancing the performance of web applications.
Tailwind CSS provides utility-first CSS classes, allowing for rapid styling without leaving your HTML markup.
Yes, Payload is designed to be flexible and can be integrated with various frontend frameworks, though this guide focuses on NextJS.
By following this guide, you will have a solid foundation for building dynamic websites using Payload NextJS. Don't forget to explore more resources on the AllAboutPayload website for deeper insights and updates.