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
- Technology Stack
- Project Structure
- Core Architecture
- Key Features
- Content Management
- Component System
- Routing & Data Fetching
- Development Workflow
- Environment Configuration
- Type System
- Performance Optimizations
- SEO & Metadata
- Live Preview
- Getting Started Guide
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-staticexport 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
-
Page Component (
app/[[...slug]]/page.tsx)- Fetches page data from Contentstack
- Generates metadata for SEO
- Handles preview mode
-
Page Wrapper (
components/pages/Page.tsx)- Renders page structure (Hero, components)
- Handles JSON-LD structured data
- Manages breadcrumbs
-
Components Renderer (
components/system/ComponentsRenderer.tsx)- Maps CMS component data to React components
- Handles Live Preview attributes
- Provides error boundaries for missing components
-
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
urlfield - 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_PREVIEWContent 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:
-
Atoms (
components/atoms/)- Smallest, indivisible UI elements
- Examples: Button, Icons, MediaItem, Title
- No dependencies on other components
-
Molecules (
components/molecules/)- Simple combinations of atoms
- Examples: SearchBar (Input + Icon), AuthorCard (Media + Text)
- Only depend on atoms
-
Organisms (
components/organisms/)- Complex components composed of molecules/atoms
- Examples: Header, Footer, Hero, List
- Can depend on other organisms
-
Pages (
components/pages/)- Page-level compositions
- Examples: Page, Blog, Preview
- Compose organisms into full layouts
-
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
-
Route Handler (
app/[[...slug]]/page.tsx)- Receives
params(Next.js async params) - Calls shared helpers in
lib/contentstack/routeUtils.tsx
- Receives
-
Data Utility (
lib/contentstack/pageUtils.ts)- Builds path from params
- Calls cached Contentstack query
- Returns typed content data
-
Caching Strategy
- React
cache()for request deduplication - ISR for static regeneration
- 30-minute revalidation window
- React
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.tsxfor centralized styling and UX.
Development Workflow
Getting Started
-
Install dependencies:
npm install -
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 -
Generate TypeScript types:
npm run generate-typesThis generates
types/contentstack.d.tsfrom your Contentstack schema. -
Start development server:
npm run dev
Available Scripts
npm run dev- Start development servernpm run build- Build for productionnpm run start- Start production servernpm run lint- Run ESLintnpm run typecheck- Run TypeScript type checkingnpm 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-docRun 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 metadataRegion 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 mappingComponentsRendererProps- Renderer propsPageParams,BlogParams- Route parameters- Extended
Taxonomytype withterm_uid
Type Safety Features
- Strict TypeScript configuration
- No
anytypes (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
adjustFontFallbackinapp/layout.tsxto 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.ts → getJsonLd().
Open Graph Tags
- Title, description, URL
- Image with dimensions (1200x630)
- Automatic fallback image generation via
/api/ogwhen 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_tokenImplementation
-
SDK Configuration (
lib/contentstack/config.ts)- Live Preview enabled in stack config
- Preview host and token configured
-
Client Initialization (
lib/contentstack/config.ts)initLivePreview()sets up client-side preview- Edit buttons enabled
- Builder mode activated
-
Component Rendering (
components/system/ComponentsRenderer.tsx)- CSLP attributes added to components
- Editable tags from Contentstack SDK
- Empty state handling for preview
-
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
- Read this document to understand the architecture
- Review component docs in
docs/folder - Check types in
types/to understand data structures - Examine examples in
components/for patterns - Follow Atomic Design principles when creating components
For Developers
- Set up environment (see Environment Configuration)
- Generate types (
npm run generate-types) - Start dev server (
npm run dev) - Create components following Atomic Design structure
- Add types to
types/types.tsif needed - Document components in
docs/folder
Common Tasks
Adding a new component:
- Create component in appropriate folder (atoms/molecules/organisms)
- Add to
ComponentsRendererif it's a CMS component - Update types if needed
- Document in
docs/folder
Adding a new content type:
- Create in Contentstack
- Run
npm run generate-types - Add query function in
lib/contentstack/queries.ts - Create page component if needed
- Add route handler in
app/
Modifying styling:
- Use Tailwind classes in components
- Add custom tokens to
styles/tokens.cssif needed - Update theme variables in
styles/theme.css
Additional Resources
- Component Documentation: See
docs/README.mdfor component details - Contentstack Docs: https://www.contentstack.com/docs
- Next.js Docs: https://nextjs.org/docs
- Tailwind CSS Docs: https://tailwindcss.com/docs
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