dot CMS

Mastering dotCMS Content API Integration with Next.js

Mastering dotCMS Content API Integration with Next.js
Author image

Freddy Montes

Product Manager

Share this article on:

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

  1. Error Handling: Always implement robust error handling to manage API failures gracefully or unexpected responses.

  2. Loading States: Provide clear loading indicators to improve user experience while content is being fetched.

  3. Pagination: For larger collections, implement pagination to improve performance and user experience.

  4. SEO Optimization: Leverage Next.js' server-side rendering capabilities for better SEO.

  5. Caching: Implement caching strategies to reduce API calls and improve performance.

  6. 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!