Getting Started: The .env File
To connect this app to your own CMS instance, you only need to configure your HEADLESSLI_TOKEN environment variable with your Headless.li API token.
- HEADLESSLI_TOKEN: (Required) You can get a free token for testing by making an account on http://www.headless.li .
The Infrastructure Stack
- DatoCMS (or any other headless CMS): Acts as your "Single Source of Truth" for content, assets, and SEO metadata.
- Headless.li Middleware: Acts as a typed orchestrator. It performs an introspection of your CMS schema and provides a cleaned "Tree" of data to your frontend.
- Next.js Frontend: Renders the data using the
QueenofheartsRenderComponent, which maps backend records to your local React components.
DatoCMS Development Quirks
Professional Headless CMSs have specific behaviors that impact how you write your code. Keep these three rules in mind:
- The "Record" Suffix: DatoCMS appends
Record to every model API ID. When registering components in src/registerComponents.ts, you must use this name (e.g., HeroRecord, PageRecord).
- Lowercase Mapping: The GraphQL schema often normalizes field names to lowercase. If you defined
buttonLabel in the admin dashboard, it will arrive at your component as buttonlabel. Update your TypeScript interfaces accordingly.
- Asset Objects: Images are not simple strings; they are rich objects. To display an image, access
image.url. You also have access to alt text and responsive metadata within the same object.
How to Register Components
To render a CMS block, you must map the backend __typename to a local React component in registerComponents.ts:
registerLazyComponent(
() => import('./blocks/Hero'),
'HeroRecord'
);
Troubleshooting
- Page Not Found: Ensure the slug in the CMS matches the URL you are visiting.
- Empty Data: By default, the API only fetches Published content. If you are seeing 404s or null data, ensure you have clicked the "Publish" button in the DatoCMS editor.
- Case Sensitivity: If a specific field is missing, check the network response or Postman. The middleware follows the DatoCMS GraphQL schema strictly, which often favors lowercase identifiers.
6. How the "Magic" Happens
Headless.li uses a declarative rendering pattern. You don't manually map data to components in your routes; instead, the system uses a three-pillar approach to build your page dynamically:
- Pillar 1: The CMS Tree: When you request a page, the CMS returns a "Tree" of data. Every block in your Paragraphs field arrives with a
__typename (e.g., HeroRecord).
- Pillar 2: The Registry: Inside
registerComponents.ts, you tell the app which React component handles which Typename. This creates a "Map" that the middleware uses to understand your frontend architecture.
- Pillar 3: The Render Component: The
<QueenofheartsRenderComponent /> is the engine. It takes the CMS Tree and the Registry Map, matches them up, and injects the correct data into the correct React components automatically.
Example Workflow:
- You add a Call To Action block in DatoCMS.
- The API returns a
CalltoactionRecord object.
- The Registry finds the local
CallToAction.tsx component.
- The Render Component places that component on the screen and passes it the
title and buttonlabel props.
This architecture allows you to change the order of your website directly from the CMS dashboard without touching a single line of code or redeploying your frontend.