dotCMS, the top Universal Content Management System, provides powerful content management features for modern web applications. This guide explains how to use the dotCMS content API in a Next.js application, boosting your site’s dynamic capabilities, content flexibility, and SEO.
By integrating dotCMS with Next.js, you'll be able to:
Create highly dynamic and responsive web applications
Manage content efficiently through dotCMS's intuitive interface
Leverage Next.js' server-side rendering for improved SEO
Achieve faster load times and better performance
Setting Up the dotCMS Client
Installation
First, you need to install the @dotcms/client library in your Next.js project:
npm install @dotcms/client --save
Initialization
Then import and initialize the client with your dotCMS host and authentication token to connect to your dotCMS instance:
import { dotcmsClient } from "@dotcms/client";
const client = dotcmsClient.init({
dotcmsUrl: process.env.NEXT_PUBLIC_DOTCMS_HOST,
authToken: process.env.NEXT_PUBLIC_DOTCMS_AUTH_TOKEN,
});
Make sure to set the NEXT_PUBLIC_DOTCMS_HOST and NEXT_PUBLIC_DOTCMS_AUTH_TOKEN in your .env.local file:
NEXT_PUBLIC_DOTCMS_HOST=https://your-dotcms-instance.com
NEXT_PUBLIC_DOTCMS_AUTH_TOKEN=your-auth-token
Important Security Note: Ensure that the auth token used has only read permissions to minimize security risks in client-side applications.
Building your dynamic component
Let's create a dynamic blog list component that fetches and displays the latest blog posts from dotCMS.
Creating the BlogList Component
Create a new file components/BlogList.js:
import { useState, useEffect } from 'react';
import client from '../dotcmsClient';
import BlogItem from './BlogItem';
export default function BlogList() {
const [blogs, setBlogs] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetchBlogs();
}, []);
const fetchBlogs = async () => {
try {
const response = await client.content
.getCollection("Blog")
.sortBy([{ field: "modDate", order: "desc" }])
.limit(3)
.fetch();
setBlogs(response.contentlets);
setLoading(false);
} catch (error) {
console.error(`Error fetching Blogs`, error);
setError('Failed to fetch blogs. Please try again later.');
setLoading(false);
}
};
if (loading) return <div>Loading...</div>;
if (error) return <div>{error}</div>;
return (
<div className="flex flex-col">
<h2 className="text-2xl font-bold mb-7 text-black">Latest Blog Posts</h2>
<ul className="space-y-4">
{blogs.map(contentlet => (
<li key={contentlet.identifier}>
<BlogItem data={contentlet} />
</li>
))}
</ul>
</div>
);
}
Creating the BlogItem Component
Now, let's create the BlogItem component in components/BlogItem.js:
import Image from 'next/image';
export default function BlogItem({ data }) {
const dateFormatOptions = { year: 'numeric', month: 'long', day: 'numeric' };
return (
<div className="flex items-center space-x-4">
<div className="relative w-32 h-32">
<Image
src={`${process.env.NEXT_PUBLIC_DOTCMS_HOST}${data.image}?language_id=${data.languageId || 1}`}
alt={data.urlTitle}
layout="fill"
objectFit="cover"
className="rounded-lg"
/>
</div>
<div className="flex flex-col">
<a
href={data.urlMap || data.url}
className="text-lg font-semibold text-zinc-900 hover:underline"
>
{data.title}
</a>
<time className="text-sm text-zinc-600">
{new Date(data.modDate).toLocaleDateString(
"en-US",
dateFormatOptions
)}
</time>
<p className="mt-2 text-zinc-700">{data.description}</p>
</div>
</div>
);
}
Using the Components
You can now use the BlogList component in any of your pages. For example, in your pages/index.js:
import BlogList from '../components/BlogList';
export default function Home() {
return (
<div className="container mx-auto px-4 py-8">
<h1 className="text-4xl font-bold mb-8">Welcome to Our Blog</h1>
<BlogList />
</div>
);
}
Best Practices and Optimizations
Error Handling: Always implement robust error handling to manage API failures gracefully or unexpected responses.
Loading States: Provide clear loading indicators to improve user experience while content is being fetched.
Pagination: For larger collections, implement pagination to improve performance and user experience.
SEO Optimization: Leverage Next.js' server-side rendering capabilities for better SEO.
Caching: Implement caching strategies to reduce API calls and improve performance.
Type Safety: If using TypeScript, define interfaces for your content types to improve type safety and developer experience.
Conclusion
The dotCMS content API is a powerful tool that allows you to retrieve content of any kind, with flexible filtering and pagination options. Integrating the dotCMS content API with Next.js opens up a world of possibilities for creating dynamic, content-rich web applications.
You now know the basics of setting up the dotCMS client, creating dynamic components, and fetching content!