Skip to main content
Our new developer certification is live!

Architecture & Features Overview

This document provides a comprehensive overview of the Contentstack Developer Homebase project architecture, features, and technical implementation details. It's designed to help AI agents and developers quickly understand the codebase and get started.

Table of Contents


Project Overview

Contentstack Developer Homebase is a Next.js-based developer documentation portal that serves as the central hub for Contentstack developers. It provides:

  • Comprehensive documentation and guides
  • Technical blog posts
  • SDK documentation
  • API references
  • AI/agent integration examples
  • Live preview capabilities for content editors

The site is built with a headless CMS architecture, using Contentstack as the content backend, enabling content editors to manage all site content without code changes.


Technology Stack

Core Framework

  • Next.js 16.1.4 - React framework with App Router
  • React 19.2.3 - UI library
  • TypeScript 5 - Type safety

Styling

  • Tailwind CSS 4 - Utility-first CSS framework
  • PostCSS - CSS processing
  • Custom CSS Variables - Theme tokens in styles/tokens.css

Content Management

  • @contentstack/delivery-sdk (v4.11.0) - Contentstack Delivery SDK
  • @contentstack/live-preview-utils (v4.2.0) - Live Preview integration
  • Custom RichTextRenderer - Custom JSON RTE to React component renderer

UI Components & Icons

  • @iconify/react - Icon library
  • @iconify/icons-material-symbols - Material Symbols icon set
  • next-themes - Theme management (dark/light mode)
  • react-syntax-highlighter - Code syntax highlighting

Utilities

  • clsx - Conditional class names
  • tailwind-merge - Merge Tailwind classes
  • @timbenniks/contentstack-endpoints - Contentstack endpoint utilities

Development Tools

  • ESLint - Code linting
  • TypeScript - Type checking

Project Structure

developers.contentstack.com/ ├── app/ # Next.js App Router pages │ ├── [[...slug]]/ # Dynamic catch-all route for pages │ │ └── page.tsx # Page component with ISR │ ├── blog/ │ │ └── [slug]/ # Blog post route │ │ └── page.tsx │ ├── md/ # Markdown route handlers │ │ └── blog/ │ ├── layout.tsx # Root layout with fonts & metadata │ └── favicon.ico │ ├── components/ # React components (Atomic Design) │ ├── atoms/ # Basic UI elements │ │ ├── Button.tsx │ │ ├── Icons.tsx │ │ ├── MediaItem.tsx │ │ ├── RichTextRenderer.tsx │ │ └── ... │ ├── molecules/ # Simple component combinations │ │ ├── SearchBar.tsx │ │ ├── AuthorCard.tsx │ │ ├── Breadcrumb.tsx │ │ └── ... │ ├── organisms/ # Complex components │ │ ├── Header.tsx │ │ ├── Footer.tsx │ │ ├── Hero.tsx │ │ ├── List.tsx │ │ └── ... │ ├── layout/ # Layout-specific components │ │ ├── DesktopNavigation.tsx │ │ ├── MobileNavigation.tsx │ │ └── ThemeAwareLogo.tsx │ ├── pages/ # Page-level components │ │ ├── Page.tsx │ │ ├── Blog.tsx │ │ └── Preview.tsx │ └── system/ # System-level components │ ├── ComponentsRenderer.tsx │ ├── ErrorBoundary.tsx │ └── ClientErrorBoundary.tsx │ ├── lib/ # Utility functions & configurations │ ├── contentstack/ # Contentstack SDK module │ │ ├── index.ts # Main exports (re-exports) │ │ ├── config.ts # Stack initialization & Live Preview │ │ ├── queries.ts # Content fetching functions │ │ ├── queries/cards.ts # Card query utilities │ │ ├── header.ts # Header fetching │ │ ├── metadata.ts # JSON-LD & OG tags │ │ ├── filters.ts # Filtered content & facets │ │ ├── sitemap.ts # Sitemap utilities │ │ ├── searchQueries.ts # Search query builders │ │ └── pageUtils.ts # Page data fetching utilities │ │ └── routeUtils.tsx # Shared page-route helpers │ ├── markdown/ # Markdown utilities │ │ └── routeUtils.ts # Shared markdown-route helpers │ ├── transform/ # Data transformation utilities │ │ ├── listUtils.ts # List component utilities │ │ └── headerUtils.ts # Header transformation │ ├── utils.ts # General utilities (cn, etc.) │ └── env.ts # Environment variable handling │ ├── types/ # TypeScript type definitions │ ├── contentstack.d.ts # Generated Contentstack types │ └── types.ts # Application-specific types │ ├── styles/ # Global styles │ ├── globals.css # Global styles & Tailwind imports │ ├── theme.css # Theme variables │ └── tokens.css # Design tokens │ ├── public/ # Static assets │ ├── fonts/ # Custom fonts (Tercia, Material Symbols) │ └── *.svg # Logo files │ └── docs/ # Component documentation ├── atoms/ ├── molecules/ ├── organisms/ └── README.md

Core Architecture

Rendering Strategy

The application uses Incremental Static Regeneration (ISR) for optimal performance:

  • Static Generation with force-static export mode
  • Revalidation every 30 minutes (1800 seconds)
  • On-demand regeneration via Contentstack webhooks (future)

Data Flow

Contentstack CMS ↓ (API calls) lib/contentstack/ (SDK queries) ├── config.ts (stack initialization) ├── queries.ts (content fetching) └── pageUtils.ts (data utilities) ↓ (typed data) app/[[...slug]]/page.tsx (page component) ↓ (props) components/pages/Page.tsx ↓ (component mapping) components/system/ComponentsRenderer.tsx ↓ (rendered components) components/organisms/* (Hero, List, Media, etc.)

Component Rendering Pipeline

  1. Page Component (app/[[...slug]]/page.tsx)

    • Fetches page data from Contentstack
    • Generates metadata for SEO
    • Handles preview mode
  2. Page Wrapper (components/pages/Page.tsx)

    • Renders page structure (Hero, components)
    • Handles JSON-LD structured data
    • Manages breadcrumbs
  3. Components Renderer (components/system/ComponentsRenderer.tsx)

    • Maps CMS component data to React components
    • Handles Live Preview attributes
    • Provides error boundaries for missing components
  4. Organisms (components/organisms/*)

    • Render complex UI sections
    • Compose molecules and atoms
    • Handle component-specific logic

Key Features

1. Dynamic Page Routing

  • Catch-all routes ([[...slug]]) handle all page URLs dynamically
  • URLs are stored in Contentstack and matched via url field
  • Supports nested paths (e.g., /guides/getting-started/nextjs)

2. Blog System

  • Dedicated /blog/[slug] route for blog posts
  • Person references with full person data (used as authors)
  • Taxonomy tagging system
  • Blog listing pages with filtering

3. Component-Based Content

Content is structured as reusable components in Contentstack:

  • Hero - Page headers with title, description, CTA
  • List - Card grids with query-based or manual card selection
  • Media - Image/video sections
  • Rich Text - WYSIWYG content blocks
  • FAQ - Accordion-style Q&A sections
  • Notice - Alert/info boxes

4. Live Preview

  • Real-time content preview in Contentstack UI
  • Edit buttons overlay on preview elements
  • Supports both page and blog post previews
  • Client-side preview updates without page refresh

5. Content Enrichment

List Components can dynamically fetch content:

  • Query by content type (page, blogpost, guide, etc.)
  • Filter and sort options
  • Merge with manually selected cards
  • Supports pagination and limits

6. SEO Optimization

  • JSON-LD structured data for rich snippets
  • Open Graph tags for social sharing
  • Twitter Card metadata
  • Dynamic metadata generation per page
  • Schema.org types (Article, WebPage, Person, etc.)

7. Theme Support

  • Dark mode by default
  • Theme-aware logos
  • CSS custom properties for theming
  • Smooth theme transitions

8. Type Safety

  • Generated types from Contentstack schema (types/contentstack.d.ts)
  • Application types for component props (types/types.ts)
  • Full TypeScript coverage across the codebase

Content Management

Contentstack Configuration

The Contentstack SDK is configured in lib/contentstack/config.ts:

- API Key: NEXT_PUBLIC_CONTENTSTACK_API_KEY
- Delivery Token: NEXT_PUBLIC_CONTENTSTACK_DELIVERY_TOKEN
- Environment: NEXT_PUBLIC_CONTENTSTACK_ENVIRONMENT
- Region: NEXT_PUBLIC_CONTENTSTACK_REGION (optional)
- Live Preview: NEXT_PUBLIC_CONTENTSTACK_PREVIEW

Content Types

Page (page content type)

  • URL field (unique identifier)
  • Title, description, metadata
  • Components array (Hero, List, Media, etc.)
  • SEO fields (schema_type, custom_json_ld)

Blogpost (blogpost content type)

  • URL field (slug-based)
  • Author reference (Person[])
  • Taxonomy tags
  • Publication date
  • Rich text content

Person (person content type)

  • Name, bio, job title, avatar
  • URL for person pages
  • Used as authors for blog posts and guides
  • Used as hosts/guests for live streams

Guide, LiveStream, List - Additional content types

Query Patterns

Page Query:

stack.contentType("page")
  .entry()
  .query()
  .where('url', QueryOperation.EQUALS, url)
  .find<Page>()

Blog Query:

stack.contentType("blogpost")
  .entry()
  .includeReference(["author"])
  .query()
  .where('url', QueryOperation.EQUALS, url)
  .find<Blogpost>()

Dynamic List Query:

stack.contentType(contentType)
  .entry()
  .query()
  .limit(limit)
  .find<Page | Blogpost | Guide>()

Component System

Atomic Design Principles

The component architecture follows Atomic Design:

  1. Atoms (components/atoms/)

    • Smallest, indivisible UI elements
    • Examples: Button, Icons, MediaItem, Title
    • No dependencies on other components
  2. Molecules (components/molecules/)

    • Simple combinations of atoms
    • Examples: SearchBar (Input + Icon), AuthorCard (Media + Text)
    • Only depend on atoms
  3. Organisms (components/organisms/)

    • Complex components composed of molecules/atoms
    • Examples: Header, Footer, Hero, List
    • Can depend on other organisms
  4. Pages (components/pages/)

    • Page-level compositions
    • Examples: Page, Blog, Preview
    • Compose organisms into full layouts
  5. System (components/system/)

    • Infrastructure components
    • Examples: ComponentsRenderer, ErrorBoundary
    • Handle rendering logic and error states

Component Mapping

The ComponentsRenderer maps CMS component data to React components:

const componentMap = {
  hero: Hero,
  list: List,
  media: Media,
} as const;

Components are identified by their key in the CMS response and rendered with their props.

Dependency Rules

  • Atoms → No dependencies
  • Molecules → Atoms only
  • Organisms → Molecules, Atoms, other Organisms
  • Pages → Organisms, Molecules, Atoms
  • System → All component types

Routing & Data Fetching

Route Structure

/ → Home page (slug: []) /guides → Guides page (slug: ['guides']) /guides/getting-started → Nested page (slug: ['guides', 'getting-started']) /blog/[slug] → Blog post (slug: 'my-post')

Data Fetching Pattern

  1. Route Handler (app/[[...slug]]/page.tsx)

    • Receives params (Next.js async params)
    • Calls shared helpers in lib/contentstack/routeUtils.tsx
  2. Data Utility (lib/contentstack/pageUtils.ts)

    • Builds path from params
    • Calls cached Contentstack query
    • Returns typed content data
  3. Caching Strategy

    • React cache() for request deduplication
    • ISR for static regeneration
    • 30-minute revalidation window

Metadata Generation

Metadata is generated server-side for each page:

export const generateMetadata = createMetadataGenerator("page");

Includes:

  • Page title and description
  • Open Graph tags
  • Twitter Card metadata
  • Dynamic images from CMS

Not Found Handling

The app uses a custom 404 route:

  • app/not-found.tsx for centralized styling and UX.

Development Workflow

Getting Started

  1. Install dependencies:

    npm install
  2. Set up environment variables:

    # Copy .env.example (if exists) or create .env.local
    NEXT_PUBLIC_CONTENTSTACK_API_KEY=your_api_key
    NEXT_PUBLIC_CONTENTSTACK_DELIVERY_TOKEN=your_token
    NEXT_PUBLIC_CONTENTSTACK_ENVIRONMENT=your_environment
    NEXT_PUBLIC_CONTENTSTACK_PREVIEW=false
  3. Generate TypeScript types:

    npm run generate-types

    This generates types/contentstack.d.ts from your Contentstack schema.

  4. Start development server:

    npm run dev

Available Scripts

  • npm run dev - Start development server
  • npm run build - Build for production
  • npm run start - Start production server
  • npm run lint - Run ESLint
  • npm run typecheck - Run TypeScript type checking
  • npm run generate-types - Generate Contentstack types

Type Generation

The generate-types script uses Contentstack CLI:

npx @contentstack/cli tsgen \
  -o types/contentstack.d.ts \
  -a developers-delivery \
  --include-editable-tags \
  --include-system-fields \
  --no-doc

Run this whenever your Contentstack schema changes.


Environment Configuration

Required Variables

NEXT_PUBLIC_CONTENTSTACK_API_KEY          # Contentstack API key
NEXT_PUBLIC_CONTENTSTACK_DELIVERY_TOKEN   # Delivery token
NEXT_PUBLIC_CONTENTSTACK_ENVIRONMENT      # Environment name (e.g., 'production')

Optional Variables

NEXT_PUBLIC_CONTENTSTACK_REGION           # Region (us, eu, azure-na, etc.)
NEXT_PUBLIC_CONTENTSTACK_PREVIEW          # Enable Live Preview ('true'/'false')
NEXT_PUBLIC_CONTENTSTACK_PREVIEW_TOKEN    # Preview token (if preview enabled)
NEXT_PUBLIC_CONTENTSTACK_PREVIEW_HOST     # Preview host override
NEXT_PUBLIC_CONTENTSTACK_CONTENT_DELIVERY # CDN host override
NEXT_PUBLIC_CONTENTSTACK_CONTENT_APPLICATION # App host override
NEXT_PUBLIC_SITE_URL                      # Site URL for metadata

Region Support

The project supports multiple Contentstack regions via @timbenniks/contentstack-endpoints:

  • US (default)
  • EU
  • Azure regions
  • Custom endpoints

Type System

Generated Types

types/contentstack.d.ts contains types generated from your Contentstack schema:

  • Content type definitions (Page, Blogpost, Person, etc.)
  • Field types (RichText, File, Link, etc.)
  • System fields (uid, created_at, updated_at, etc.)

Application Types

types/types.ts extends generated types with application-specific types:

  • ComponentKV - Component key-value mapping
  • ComponentsRendererProps - Renderer props
  • PageParams, BlogParams - Route parameters
  • Extended Taxonomy type with term_uid

Type Safety Features

  • Strict TypeScript configuration
  • No any types (project rule)
  • Type inference from Contentstack queries
  • Component prop types derived from CMS schema

Performance Optimizations

Static Generation

  • ISR with 30-minute revalidation
  • Force static export mode
  • Pre-rendered pages at build time

Image Optimization

  • Next.js Image component for automatic optimization
  • Remote patterns configured for Contentstack CDN
  • Responsive images with srcset

Font Loading

  • Next/font for Google + local fonts
  • Fallback metrics tuned via adjustFontFallback in app/layout.tsx to reduce CLS during font swap

Code Splitting

  • Automatic code splitting by Next.js
  • Dynamic imports for heavy components
  • Tree shaking via ES modules

Caching

  • React cache() for request deduplication
  • ISR for static page caching
  • CDN caching via Contentstack

SEO & Metadata

JSON-LD Structured Data

Each page generates JSON-LD based on content type:

  • WebPage - Default for pages
  • Article/BlogPosting - For blog posts
  • Person - For author pages
  • Organization - For organization pages
  • Event - For live streams
  • FAQPage - For FAQ sections

Generated in lib/contentstack/metadata.tsgetJsonLd().

Open Graph Tags

  • Title, description, URL
  • Image with dimensions (1200x630)
  • Automatic fallback image generation via /api/og when CMS metadata image is missing
  • Site name and locale
  • Dynamic per-page content

Twitter Cards

  • Summary large image cards
  • Creator attribution
  • Dynamic content

Metadata Generation Flow

Page Component ↓ generateMetadata() (Next.js) ↓ createMetadata() (lib/pageUtils.ts) ↓ createOgTags() (lib/contentstack/metadata.ts) ↓ Next.js Metadata API

Live Preview

Configuration

Live Preview is enabled via environment variables:

NEXT_PUBLIC_CONTENTSTACK_PREVIEW=true
NEXT_PUBLIC_CONTENTSTACK_PREVIEW_TOKEN=your_preview_token

Implementation

  1. SDK Configuration (lib/contentstack/config.ts)

    • Live Preview enabled in stack config
    • Preview host and token configured
  2. Client Initialization (lib/contentstack/config.ts)

    • initLivePreview() sets up client-side preview
    • Edit buttons enabled
    • Builder mode activated
  3. Component Rendering (components/system/ComponentsRenderer.tsx)

    • CSLP attributes added to components
    • Editable tags from Contentstack SDK
    • Empty state handling for preview
  4. Preview Page (components/pages/Preview.tsx)

    • Client component for preview mode
    • Initializes Live Preview on mount
    • Handles preview-specific routing

Preview Flow

Contentstack UI (Editor) ↓ (preview URL with token) Next.js Preview Route ↓ Preview Component ↓ initLivePreview() (client-side) ↓ Real-time updates via WebSocket

Getting Started Guide

For AI Agents

  1. Read this document to understand the architecture
  2. Review component docs in docs/ folder
  3. Check types in types/ to understand data structures
  4. Examine examples in components/ for patterns
  5. Follow Atomic Design principles when creating components

For Developers

  1. Set up environment (see Environment Configuration)
  2. Generate types (npm run generate-types)
  3. Start dev server (npm run dev)
  4. Create components following Atomic Design structure
  5. Add types to types/types.ts if needed
  6. Document components in docs/ folder

Common Tasks

Adding a new component:

  1. Create component in appropriate folder (atoms/molecules/organisms)
  2. Add to ComponentsRenderer if it's a CMS component
  3. Update types if needed
  4. Document in docs/ folder

Adding a new content type:

  1. Create in Contentstack
  2. Run npm run generate-types
  3. Add query function in lib/contentstack/queries.ts
  4. Create page component if needed
  5. Add route handler in app/

Modifying styling:

  1. Use Tailwind classes in components
  2. Add custom tokens to styles/tokens.css if needed
  3. Update theme variables in styles/theme.css

Additional Resources


Architecture Decisions

Why Atomic Design?

  • Reusability - Components can be composed easily
  • Maintainability - Clear component hierarchy
  • Scalability - Easy to add new components
  • Documentation - Natural organization for docs

Why ISR?

  • Performance - Fast static pages
  • Freshness - Content updates without full rebuild
  • Scalability - Handles high traffic
  • SEO - Pre-rendered pages for search engines

Why TypeScript?

  • Type Safety - Catch errors at compile time
  • Developer Experience - Better IDE support
  • Documentation - Types serve as documentation
  • Refactoring - Safe code changes

Why Contentstack?

  • Headless CMS - Decouple content from presentation
  • API-First - Easy integration
  • Live Preview - Real-time editing experience
  • Flexibility - Works with any frontend

Last updated: January 2026