MCPcopy Index your code
hub / github.com/agility/agilitycms-nextjs-starter

github.com/agility/agilitycms-nextjs-starter @main

Chat with this repo
repository ↗ · DeepWiki ↗ · + Follow
80 symbols 210 edges 50 files 0 documented · 0% updated 6mo ago★ 904 open issues
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

Agility CMS & Next.js Starter

A modern, production-ready starter for building content-managed websites with Agility CMS and Next.js 15.

Live Website Demo

New to Agility CMS? Sign up for a FREE account

✨ Features

Next.js 15 & React 18

  • App Router - Modern Next.js routing with Server Components
  • TypeScript - Full type safety throughout the project
  • Tailwind CSS 4 - Utility-first styling with dark mode support
  • Static Site Generation (SSG) - Pre-rendered pages with Incremental Static Regeneration (ISR)
  • Server Components - React Server Components for optimal performance

Agility CMS Integration

  • Dynamic Page Routing - Automatic page generation from Agility CMS sitemap
  • Component Module System - CMS components mapped to React components
  • Content Fetching - Server-side data fetching with caching strategies
  • Preview Mode - Real-time content preview for editors
  • On-Demand Revalidation - Webhook-triggered cache invalidation
  • Multi-Locale Ready - Framework supports multiple languages

Developer Experience

  • Component-Level Data Fetching - Fetch data where you need it
  • Cache Tag Strategy - Granular cache control with automatic invalidation
  • Dark Mode - Built-in dark mode toggle with persistence
  • Responsive Design - Mobile-first responsive layout
  • Image Optimization - Next.js Image component integration
  • TypeScript Interfaces - Strongly typed CMS content models

📋 Table of Contents

🚀 Quick Start

Prerequisites

  • Node.js 18.x or higher
  • npm or yarn package manager
  • An Agility CMS instance (sign up for free)

Installation

  1. Clone the repository

bash git clone https://github.com/agility/agilitycms-nextjs-starter.git cd agilitycms-nextjs-starter

  1. Install dependencies

bash npm install # or yarn install

  1. Configure environment variables

bash cp .env.local.example .env.local

  1. Get your API keys from Agility CMS

  2. Log into Agility CMS

  3. Navigate to Settings > API Keys
  4. Copy your:

    • GUID (Instance ID)
    • Live API Key (for production)
    • Preview API Key (for development/preview)
    • Security Key (for webhooks)
  5. Update .env.local with your credentials:

env AGILITY_GUID=your-guid-here AGILITY_API_FETCH_KEY=your-live-api-key AGILITY_API_PREVIEW_KEY=your-preview-api-key AGILITY_SECURITY_KEY=your-security-key AGILITY_LOCALES=en-us AGILITY_SITEMAP=website AGILITY_FETCH_CACHE_DURATION=120 AGILITY_PATH_REVALIDATE_DURATION=10

  1. Run the development server

bash npm run dev # or yarn dev

  1. Open your browser to http://localhost:3000

Production Build

npm run build
npm run start

📁 Project Structure

agilitycms-nextjs-starter/
├── app/                              # Next.js App Router
│   ├── layout.tsx                   # Root layout with header/footer
│   ├── page.tsx                     # Home page (delegates to [...slug])
│   ├── [...slug]/                   # Dynamic catch-all route
│   │   ├── page.tsx                 # Main page component with SSG
│   │   ├── error.tsx                # Error boundary
│   │   └── not-found.tsx            # 404 page
│   └── api/                         # API routes
│       ├── preview/                 # Preview mode endpoints
│       ├── preview/exit/            # Exit preview mode
│       ├── revalidate/              # Webhook for cache invalidation
│       └── dynamic-redirect/        # ContentID-based redirects
├── components/                      # React components
│   ├── agility-components/          # CMS component modules
│   │   ├── FeaturedPost.tsx        # Featured post display
│   │   ├── PostDetails.tsx         # Dynamic post detail view
│   │   ├── PostsListing/           # Infinite scroll post list
│   │   ├── TextBlockWithImage.tsx  # Flexible layout component
│   │   ├── RichTextArea.tsx        # HTML content display
│   │   ├── Heading.tsx             # Typography component
│   │   └── index.ts                # Component registry
│   ├── agility-pages/              # Page templates
│   │   ├── MainTemplate.tsx        # Main page template
│   │   └── index.ts                # Template registry
│   └── common/                     # Shared components
│       ├── SiteHeader.tsx          # Responsive header with dark mode
│       ├── SiteFooter.tsx          # Footer with social links
│       ├── PreviewBar.tsx          # Preview/Live mode toggle
│       └── InlineError.tsx         # Error display
├── lib/                            # Utilities and helpers
│   ├── cms/                        # CMS data fetching
│   │   ├── getAgilityContext.ts    # Mode detection (preview/live)
│   │   ├── getAgilitySDK.ts        # SDK initialization
│   │   ├── getAgilityPage.ts       # Fetch pages with layout
│   │   ├── getContentItem.ts       # Fetch single content item
│   │   ├── getContentList.ts       # Fetch content lists
│   │   ├── getSitemapFlat.ts       # Flat sitemap retrieval
│   │   └── getSitemapNested.ts     # Nested sitemap retrieval
│   ├── cms-content/                # Domain-specific queries
│   │   ├── getPostListing.ts       # Blog posts with URLs
│   │   ├── getHeaderContent.ts     # Header navigation data
│   │   ├── getPageMetaData.ts      # Page SEO metadata
│   │   └── resolveAgilityMetaData.ts # Advanced metadata
│   └── types/                      # TypeScript interfaces
│       └── (IPost, IAuthor, ICategory, etc.)
├── styles/
│   └── globals.css                 # Tailwind imports & global styles
├── middleware.ts                   # Next.js middleware for routing
├── .env.local.example              # Environment template
├── tailwind.config.js              # Tailwind configuration
├── next.config.js                  # Next.js configuration
└── tsconfig.json                   # TypeScript configuration

🏗️ Architecture

Dynamic Page Routing

This starter uses Next.js App Router with a catch-all dynamic route [...slug] that maps to Agility CMS pages.

How it works:

  1. Agility CMS sitemap defines your site structure
  2. generateStaticParams() pre-renders all pages at build time
  3. Each page fetches its layout template and content zones from Agility
  4. Components are dynamically loaded based on CMS configuration

See ARCHITECTURE.md for detailed explanation.

Component Module System

CMS components (modules) are mapped to React components via a registry pattern:

// components/agility-components/index.ts
const allModules = [
    {name: "TextBlockWithImage", module: TextBlockWithImage},
    {name: "Heading", module: Heading},
    {name: "FeaturedPost", module: FeaturedPost},
    {name: "PostsListing", module: PostsListing},
    {name: "PostDetails", module: PostDetails},
    {name: "RichTextArea", module: RichTextArea},
]

When Agility CMS returns a page with a "TextBlockWithImage" module, the system automatically renders the corresponding React component.

Server Components & Data Fetching

This starter uses React Server Components for optimal performance:

  • Server Components - Default for all components, fetch data server-side
  • Client Components - Used only when necessary (interactive features, hooks)
  • Component-level fetching - Each component fetches its own data
  • Parallel data fetching - Multiple components fetch concurrently

Example:

// Server Component (default)
export default async function PostDetails({module, page}) {
    const post = await getContentItem({contentID: page.contentID})
    return <article>...</article>
}

📊 Content Models

The Agility CMS instance includes the following content models:

Blog Content

  • Post - Blog posts with category, tags, author, image, and rich content
  • Author - Author profiles with name, title, and headshot
  • Category - Post categories with images and descriptions
  • Tag - Post tags for classification

Global Content

  • Header - Site header with navigation and logo
  • Footer - Site footer with links and social media
  • Global Settings - Site-wide configuration

Specialized Content

  • Testimonial Item - Customer testimonials
  • FAQ Item - Frequently asked questions
  • Pricing Tier - Pricing plans and features
  • Carousel Slide - Carousel content items

Personalization (Advanced)

  • Audience - Custom demographic targeting
  • Region - Geographic personalization
  • Customer Profile - User profiles for personalization

See CONTENT-MODELS.md for complete schema documentation.

🧩 Components

Page Components

  • MainTemplate - Standard page layout with content zones

Blog Components

  • PostsListing - Paginated blog post list with infinite scroll
  • PostDetails - Individual post view with author, category, and rich content
  • FeaturedPost - Highlighted post display

Layout Components

  • TextBlockWithImage - Flexible text + image layout (left/right)
  • RichTextArea - Rich HTML content with Tailwind prose styling
  • Heading - Page headings with various styles

Global Components

  • SiteHeader - Responsive navigation with dark mode toggle
  • SiteFooter - Footer with social links and copyright
  • PreviewBar - Preview mode indicator (development only)

See COMPONENTS.md for complete component API documentation.

🔄 Data Fetching

CMS Utilities

Located in lib/cms/, these utilities handle all Agility CMS interactions:

getAgilityContext()

Determines the current mode (preview vs. production):

const context = await getAgilityContext()
// Returns: { isPreview: boolean, locale: string, sitemap: string }

getContentItem(contentID, languageCode)

Fetches a single content item with cache tags:

const post = await getContentItem({
    contentID: 123,
    languageCode: "en-us",
})

getContentList(referenceName, languageCode, options)

Fetches content lists with pagination and filtering:

const posts = await getContentList({
    referenceName: "posts",
    languageCode: "en-us",
    take: 10,
    skip: 0,
    sort: "fields.date",
    direction: "desc",
})

getAgilityPage(slug, locale, sitemap)

Fetches a complete page with layout and content zones:

const page = await getAgilityPage({
    slug: "/blog",
    locale: "en-us",
    sitemap: "website",
})

Domain-Specific Utilities

Located in lib/cms-content/, these build on the CMS utilities for specific use cases:

  • getPostListing() - Blog posts with category filtering and URLs
  • getHeaderContent() - Navigation structure and branding
  • getPageMetaData() - SEO metadata for pages

See AGILITY-CMS-GUIDE.md for complete data fetching patterns.

💾 Caching Strategy

This starter implements a sophisticated caching strategy for optimal performance:

Cache Levels

  1. SDK Object Cache - Agility Fetch SDK caches content items

  2. Controlled by AGILITY_FETCH_CACHE_DURATION (default: 120 seconds)

  3. Works best with on-demand revalidation

  4. Next.js Route Cache - Next.js caches rendered pages

  5. Controlled by AGILITY_PATH_REVALIDATE_DURATION (default: 10 seconds)
  6. ISR (Incremental Static Regeneration) automatically updates stale pages

Cache Tags

Content fetches use cache tags for granular invalidation:

// Automatically tagged as: agility-content-{contentID}-{locale}
const post = await getContentItem({contentID: 123})

When content is published in Agility CMS, a webhook triggers revalidation:

  • Tags associated with changed content are invalidated
  • Next.js regenerates affected pages on the next request

On-Demand Revalidation

The /api/revalidate endpoint handles webhook callbacks from Agility CMS:

// Revalidates specific content items and their dependent pages
POST /api/revalidate
{
  "contentID": 123,
  "languageCode": "en-us"
}

Environment Variables

# Cache content objects for 120 seconds
AGILITY_FETCH_CACHE_DURATION=120

# Revalidate page paths every 10 seconds
AGILITY_PATH_REVALIDATE_DURATION=10

Best Practices:

  • Use higher values (120-600) with on-demand revalidation for production
  • Use lower values (10-30) or 0 without webhooks for faster content updates
  • Preview mode always bypasses cache for real-time editing

👁️ Preview Mode

Preview mode allows content editors to see draft content before publishing.

How It Works

  1. Activate Preview - Click "Preview" in Agility CMS
  2. Validation - System validates preview key and ContentID
  3. Draft Mode - Next.js draft mode is enabled
  4. Live Preview - Page displays with unpublished content
  5. Exit - Click "Exit Preview" in the preview bar

Implementation

Preview Endpoint (app/api/preview/route.ts):

```typescript // Validates request and enables draft mode export async function GET(request: Request) { const {agilitypreviewkey, ContentID, slug} = searchParams

// Validate preview key
if (agilitypreviewkey !== process.env.AGILITY_SECURITY_KEY) {
    return new Response("Invalid token", {status: 401})
}

// Enable draft mode
draftMode().enable()

// Redirect to pre

Extension points exported contracts — how you extend this code

RichText (Interface)
(no doc)
components/agility-components/RichTextArea.tsx
Props (Interface)
(no doc)
components/common/PreviewBar.tsx
ICategory (Interface)
(no doc)
lib/types/ICategory.ts
PageProps (Interface)
(no doc)
lib/cms/getAgilityPage.ts
IPostMin (Interface)
(no doc)
lib/cms-content/getPostListing.ts
IRevalidateRequest (Interface)
(no doc)
app/api/revalidate/route.ts
IHeading (Interface)
(no doc)
components/agility-components/Heading.tsx
Props (Interface)
(no doc)
components/common/SiteHeader.tsx

Core symbols most depended-on inside this repo

getAgilitySDK
called by 4
lib/cms/getAgilitySDK.ts
getAgilityContext
called by 4
lib/cms/getAgilityContext.ts
getContentList
called by 2
lib/cms/getContentList.ts
getAgilityPage
called by 2
lib/cms/getAgilityPage.ts
getPostListing
called by 2
lib/cms-content/getPostListing.ts
getHeaderContent
called by 2
lib/cms-content/getHeaderContent.ts
handleMetaTag
called by 2
lib/cms-content/resolveAgilityMetaData.ts
getPageTemplate
called by 1
components/agility-pages/index.ts

Shape

Function 51
Interface 29

Languages

TypeScript100%

Modules by API surface

lib/cms-content/getHeaderContent.ts5 symbols
lib/cms-content/getPostListing.ts4 symbols
components/agility-components/TextBlockWithImage.tsx4 symbols
components/agility-components/PostsListing/PostsListing.server.tsx4 symbols
lib/cms-content/resolveAgilityMetaData.ts3 symbols
components/common/SiteHeader.tsx3 symbols
components/common/PreviewBar.tsx3 symbols
components/agility-components/PostsListing/PostsListing.client.tsx3 symbols
app/[...slug]/page.tsx3 symbols
lib/cms/getAgilityPage.ts2 symbols
components/common/output-content-item/RawContentItem.tsx2 symbols
components/common/output-content-item/OutputNestedContentItem.tsx2 symbols

For agents

$ claude mcp add agilitycms-nextjs-starter \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page