Introduction
Build a Headless Site with dotCMS
Welcome to this hands-on guide. You'll build a real banking company website powered by dotCMS and Next.js — from a blank project to a fully working site.
This is not a tour of features. You'll write real code, connect to a real CMS, and ship something that works.
What you'll build
A banking company site with three pages:
Home page — a hero banner and a curated list of blog posts, all managed in dotCMS
Blog listing page — a dynamic list of posts where a content author controls how many appear and which fields to show, without touching code
Blog detail pages — full article content, dynamically routed by slug
The site runs entirely on your machine — dotCMS locally via Docker, Next.js via the dev server.
What you'll learn
Routing — how to use Next.js catch-all routes to let dotCMS own the URL structure
dotCMS SDK — how to use @dotcms/client and @dotcms/react (part of the dotCMS SDK) to connect your app to dotCMS
Page API — how to fetch a page from dotCMS and render everything it contains
Component registry — how to map dotCMS content types to React components
Content API — how to fetch a collection of content server-side, and why it must stay server-side
Author-driven configuration — how content authors control frontend behavior through dotCMS content, without code changes
Block editor — how to render rich text content from dotCMS
Visual editing — how to enable in-context editing with the Universal Visual Editor
SEO — how to generate dynamic metadata, Open Graph tags, and canonical URLs from dotCMS content
Structured data — how to add JSON-LD so your pages are indexed correctly by search engines and surface in AI-generated answers
By the end, your site is production-ready — optimized for search, AI discovery, and real-time content editing from dotCMS.
How dotCMS structures content
Before writing any code, it helps to know how dotCMS thinks about pages and content. You'll see these terms throughout the course.
Page — in dotCMS, pages are content too. Authors create and manage them in the admin. This means dotCMS owns the URL structure — your Next.js app doesn't define routes for each page, it asks dotCMS what's at a given URL and renders whatever comes back.
Layout — the arrangement of containers on a page, defined by the page template. It also carries flags like header and footer that tell your frontend whether to render those elements.
Container — a slot on a page where authors place contentlets and widgets. A page can have multiple containers — a hero container, a main content container. The developer maps content types to components; the author fills containers with content.
Content Type — the schema. Defines what fields a piece of content has. Blog has title, body, author, image. Banner has title, caption, image, link. Authors create content from content types.
Contentlet — an instance of a Content Type. A specific blog post, a specific banner. Its fields become the props your React components receive.
Widget — a special content type whose purpose is to configure the frontend, not display content directly. The BlogList widget on the blog page has quantity and show fields — instructions for your code, not content to render.
URL Content Map — when a contentlet (like a blog post) is mapped directly to a URL. Instead of living in a container, it's accessible via pageAsset.urlContentMap when you fetch that URL.
Put together:
Page (owned by dotCMS, mapped to a URL)
└── Layout (header/footer flags, row/column structure)
└── Containers (slots where authors place content)
└── Contentlets / Widgets (instances of a Content Type → component props)
What's already set up
The starter project includes:
The dotCMS SDK installed (@dotcms/client and @dotcms/react)
Tailwind CSS configured
A dotCMS instance pre-loaded with content: a home page, a blog listing page, and three blog posts
You'll write all the pages and components. Everything else is ready.
Prerequisites
Node.js 18+ — nodejs.org
Docker Desktop installed and running — docker.com
Basic knowledge of React and Next.js — components, props, server components
Time to complete
30–60 minutes. Docker pulls images on the first run — that's the slowest part. Everything after that moves quickly.
Next up
Chapter 1: Set Up Your Project