Modern headless CMS website with AI-powered search, internationalization, and advanced caching
A production-ready Next.js demo site showcasing Agility CMS integration with React 19, TypeScript, Tailwind CSS v4, and AI-powered search capabilities.
- Headless CMS Integration - Full Agility CMS integration with dynamic page routing
- AI-Powered Search - Azure OpenAI + Algolia integration for intelligent content search
- Internationalization - Multi-locale support with clean URL routing
- Advanced Caching - Next.js cache tags with automatic revalidation
- Preview Mode - Draft content preview with Agility CMS integration
- Audience & Region Personalization - URL-based personalization system
- View Transitions - Smooth page transitions using React ViewTransition API
- Type Safety - Strongly-typed environment variables and CMS content
- Modern Stack - Next.js 15.5.3, React 19, Tailwind CSS v4, TypeScript
- Node.js 20+
- npm or yarn
- Agility CMS instance (get one at agilitycms.com)
# Clone the repository
git clone <repository-url>
cd demosite2025
# Install dependencies
npm install
# Copy environment variables
cp .env.example .env.local
# Edit .env.local with your Agility CMS credentialsCreate a .env.local file with the following required variables:
# Agility CMS Configuration
AGILITY_GUID=your-instance-guid
AGILITY_API_FETCH_KEY=your-fetch-api-key
AGILITY_API_PREVIEW_KEY=your-preview-api-key
AGILITY_SECURITY_KEY=your-security-key
AGILITY_LOCALES=en-us,fr-ca,es-mx
AGILITY_SITEMAP=website
AGILITY_FETCH_CACHE_DURATION=60
AGILITY_PATH_REVALIDATE_DURATION=60
# PostHog Analytics (Optional)
NEXT_PUBLIC_POSTHOG_KEY=your-posthog-key
NEXT_PUBLIC_POSTHOG_HOST=https://app.posthog.com
# Node Environment
NODE_ENV=development
# Build Hook (Optional - for redirect rebuilds)
BUILD_HOOK_URL=https://your-build-hook-url# Start development server with Turbopack
npm run dev
# Run prebuild (rebuilds redirect cache - required before production build)
npm run prebuild
# Build for production
npm run build
# Start production server
npm run start
# Run linter
npm run lintnpm run prebuild before npm run build to rebuild the redirect cache.
src/
├── app/ # Next.js App Router
│ ├── [locale]/ # Internationalized routes
│ │ └── [...slug]/ # Dynamic page routes
│ └── api/ # API routes
│ ├── ai/ # AI search endpoints
│ ├── preview/ # Preview mode handling
│ ├── revalidate/ # Cache revalidation webhook
│ └── dynamic-redirect/ # Content ID redirects
├── components/
│ ├── agility-components/ # CMS-connected components
│ ├── agility-pages/ # Page templates
│ ├── ai-agent/ # AI chat interface
│ ├── ai-elements/ # AI-powered UI elements
│ ├── ai-search/ # AI search components
│ ├── header/ # Navigation components
│ └── footer/ # Footer components
├── lib/
│ ├── cms/ # Agility CMS SDK wrappers
│ ├── cms-content/ # Content processing utilities
│ ├── ai/ # AI integration utilities
│ ├── posthog/ # Analytics integration
│ ├── hooks/ # React hooks
│ ├── i18n/ # Internationalization config
│ ├── types/ # TypeScript definitions
│ └── utils/ # Utility functions
└── public/ # Static assets
Content managed in Agility CMS → API fetching → Next.js rendering
- Page Routing: Dynamic via Agility's sitemap
- Content Zones:
<ContentZone name="main-content-zone">renders CMS modules - Module System: Components auto-registered via
getModule()function
src/middleware.ts→ Handles preview, redirects, i18n routingsrc/lib/cms/→ All CMS API abstractions with cachingsrc/components/agility-components/→ CMS-bound components
- Framework: Next.js 15.5.3 (App Router)
- React: 19.1.0
- TypeScript: 5.x
- Styling: Tailwind CSS v4 (CSS-file based)
- CMS: Agility CMS (@agility/nextjs 15.0.7)
- Animations: Motion 12.23.0
- AI: Azure OpenAI + Algolia
- Analytics: PostHog
- Icons: Heroicons v2, React Icons
All Agility CMS components must be registered in src/components/agility-components/index.ts:
import { ComponentName } from "./ComponentName"
const allModules = [
{ name: "ComponentName", module: ComponentName },
// ... other modules
]export const ComponentName = async ({ module, languageCode }: UnloadedModuleProps) => {
const { fields, contentID } = await getContentItem<IComponentType>({
contentID: module.contentid,
languageCode,
})
return (
<div data-agility-component={contentID}>
<div data-agility-field="fieldName">{fields.fieldName}</div>
</div>
)
}// Get parent content with nested reference
const { fields: { nestedRef: { referencename } } } = await getContentItem<MainType>({
contentID: module.contentid,
languageCode,
})
// Fetch nested collection separately
const nestedItems = await getContentList<NestedType>({
referenceName: referencename,
languageCode,
take: 20
})Always use <AgilityPic> for Agility CMS images:
import { AgilityPic } from "@agility/nextjs"
<AgilityPic
image={imageField}
fallbackWidth={600}
className="w-full h-auto"
data-agility-field="image"
/>Use renderHTML() from Agility SDK:
import { renderHTML } from "@agility/nextjs"
<div
data-agility-field="textblob"
data-agility-html
className="prose dark:prose-invert"
dangerouslySetInnerHTML={renderHTML(htmlField)}
/>The site supports multiple locales with clean URL routing:
- Default Locale: No path prefix (e.g.,
/blog) - Other Locales: Explicit prefix (e.g.,
/fr/blog,/es/blog)
Locales are configured via AGILITY_LOCALES environment variable (comma-separated).
URL-based personalization system using query parameters:
// Client component
const { selectedAudience, setAudience } = useAudienceRegionParams(audiences, regions)
// Server component
const audienceContentID = await getAudienceContentID(searchParams, locale)- Automatic Cache Tags: All CMS fetches include Next.js cache tags
- Tag Format:
agility-content-{contentID|referenceName}-{locale} - Revalidation: 60-second cache + tag-based invalidation
- Webhook:
/api/revalidatereceives Agility CMS publish events
AI-powered search using Azure OpenAI and Algolia:
- Endpoint:
/api/ai/search - Features: Streaming responses, tool calling, rate limiting
- Components: Chat interface, message history, markdown rendering
- Set all required environment variables
- Run
npm run prebuildto rebuild redirect cache - Run
npm run buildfor production build
- Preview Mode: Automatically enabled in development
- Redirects: Bloom filter cache must be rebuilt before production
- Cache Revalidation: Configure webhook in Agility CMS to point to
/api/revalidate
- Cursor Rules - Comprehensive development guidelines
- Claude Context - Detailed project context
- Copilot Instructions - AI assistant guidelines
- View Transitions - View transition implementation
- Audience & Region System - Personalization docs
- Multi-Locale Implementation - i18n details
- Environment Variables - Env var reference
- Ensure
agilitypreviewkeyparam is present (not justAgilityPreview) - Check that
AGILITY_API_PREVIEW_KEYis set correctly
- Run
npm run prebuildbefore building - Check that
data/redirections-bloom-filter.jsonexists
- Verify component is registered in
src/components/agility-components/index.ts - Check that component name matches Agility CMS module name (case-insensitive)
- Verify webhook is configured in Agility CMS
- Check
/api/revalidateendpoint is accessible - Ensure
AGILITY_SECURITY_KEYmatches webhook configuration
- Follow existing code patterns and conventions
- Register new components in
index.ts - Use TypeScript for all new code
- Follow Tailwind CSS v4 patterns
- Add proper TypeScript interfaces for CMS content
- Test with multiple locales if applicable
This project is licensed under the MIT License - see the LICENSE file for details.
Built with ❤️ using Agility CMS and Next.js