Mastering dotCMS Content API Integration with Next.js
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!