@djangocfg/nextjs
v2.1.260
Published
Next.js server utilities: sitemap, health, OG images, contact forms, navigation, config
Maintainers
Readme

@djangocfg/nextjs
Server-side Next.js utilities: OG images, sitemap, health checks, i18n, PWA, navigation, and config
Part of DjangoCFG — a modern Django framework for building production-ready SaaS applications. All @djangocfg/* packages are designed to work together, providing type-safe configuration, real-time features, and beautiful admin interfaces out of the box.
Overview
@djangocfg/nextjs provides server-side utilities for Next.js applications built on top of Django-CFG.
Note: Client components (legal pages, error pages, redirect components) are in
@djangocfg/layouts.
Features
- OG Images — typed URL builder for Django's
django_ogimagerenderer (@djangocfg/nextjs/og-image) - i18n — full next-intl integration with routing, middleware, and components
- PWA — zero-config service worker and manifest
- Base Next.js Config — reusable
createBaseNextConfig()factory for monorepos - Sitemap — dynamic XML sitemap with i18n hreflang support
- Health Checks — production-ready health monitoring endpoints
- Navigation — route definitions, menu generation, and active-state helpers
- AI Documentation — search DjangoCFG docs via MCP server and CLI
Installation
npm install @djangocfg/nextjs
# or
pnpm add @djangocfg/nextjs
# or
yarn add @djangocfg/nextjsQuick Start
AI Documentation Search
Search DjangoCFG documentation from the terminal:
# CLI (works anywhere via npx)
npx @djangocfg/nextjs ai-docs search "database configuration"
npx @djangocfg/nextjs ai-docs mcpOr use the TypeScript API:
import { search, getDocs, getMcpConfig } from '@djangocfg/nextjs/ai';
// Search documentation
const results = await search('database configuration');
results.forEach(r => console.log(r.title, r.url));
// Get formatted docs
const docs = await getDocs('How to configure PostgreSQL?');
// Get MCP server config for AI assistants
const config = getMcpConfig();MCP Server for AI Assistants
Add to your AI assistant configuration:
{
"mcpServers": {
"djangocfg-docs": {
"url": "https://mcp.djangocfg.com/mcp"
}
}
}Base Next.js Configuration
Create a reusable base configuration for all your Next.js projects:
// next.config.ts
import { createBaseNextConfig } from '@djangocfg/nextjs/config';
import bundleAnalyzer from '@next/bundle-analyzer';
const withBundleAnalyzer = bundleAnalyzer({
enabled: process.env.ANALYZE === 'true',
});
export default withBundleAnalyzer(createBaseNextConfig({
// Base path for static builds
basePath: process.env.NEXT_PUBLIC_STATIC_BUILD === 'true' ? '/cfg/admin' : undefined,
// Add custom transpile packages
transpilePackages: ['my-custom-package'],
// Custom webpack configuration (called after base webpack logic)
webpack: (config, options) => {
// Your custom webpack rules
return config;
},
}));PWA (Progressive Web App)
Zero-config PWA - Works out of the box! Service worker and offline support included automatically.
1. Create manifest
// app/manifest.ts
import { createManifest, createScreenshots } from '@djangocfg/nextjs/config';
import { settings } from '@core/settings';
export default createManifest({
name: settings.app.name,
description: settings.app.description,
themeColor: '#ffffff',
backgroundColor: '#000000',
icons: {
logo192: settings.app.icons.logo192,
logo384: settings.app.icons.logo384,
logo512: settings.app.icons.logo512,
},
// Optional: Add screenshots for Richer PWA Install UI
// IMPORTANT: Image dimensions must match sizes parameter!
// screenshots: createScreenshots([
// '/screenshots/desktop-1920x1080.png', // Wide: 1920x1080
// '/screenshots/mobile-390x844.png', // Narrow: 390x844
// ]),
});2. Add manifest metadata
// app/layout.tsx
import { createManifestMetadata } from '@djangocfg/nextjs/config';
export const metadata = {
...createManifestMetadata({
name: 'My App',
themeColor: '#000000',
}),
};That's it! PWA is now enabled in production. Generated files:
/manifest.webmanifest- Fromapp/manifest.ts/sw.js- Service worker (auto-generated in production)/workbox-*.js- Workbox runtime
Customization (optional):
// next.config.ts
export default createBaseNextConfig({
pwa: {
dest: 'public',
disable: process.env.NODE_ENV === 'development', // Disable in dev
fallbacks: {
document: '/_offline', // Offline page
},
runtimeCaching: [
// Custom caching rules
...defaultRuntimeCaching,
createApiCacheRule('https://api.example.com'),
],
},
});See PWA.md for complete guide.
i18n (Internationalization)
Full next-intl integration for multilingual Next.js apps.
Important: Use subpath imports to avoid React Context issues in server components:
@djangocfg/nextjs/i18n- Types only@djangocfg/nextjs/i18n/routing-routing,createRouting,generateLocaleParams@djangocfg/nextjs/i18n/client-I18nProvider, hooks@djangocfg/nextjs/i18n/components-LocaleSwitcher
1. Create middleware (proxy.ts)
// proxy.ts (or middleware.ts)
import createMiddleware from 'next-intl/middleware';
import { routing } from '@djangocfg/nextjs/i18n/routing';
export default createMiddleware(routing);
export const config = {
matcher: ['/((?!api|_next|_vercel|.*\\..*).*)',],
};2. Create i18n request config
// i18n/request.ts
import { getRequestConfig } from 'next-intl/server';
import { en, ru, ko } from '@djangocfg/i18n/locales';
import { mergeTranslations } from '@djangocfg/i18n/utils';
const locales = {
en: mergeTranslations(en, { app: appEn }),
ru: mergeTranslations(ru, { app: appRu }),
ko: mergeTranslations(ko, { app: appKo }),
};
export default getRequestConfig(async ({ requestLocale }) => {
let locale = await requestLocale;
if (!locale || !(locale in locales)) locale = 'en';
return {
locale,
messages: locales[locale],
timeZone: 'UTC',
};
});3. Use in layout
// app/[locale]/layout.tsx
import { getMessages } from 'next-intl/server';
import { I18nProvider } from '@djangocfg/nextjs/i18n/client';
import { routing, generateLocaleParams } from '@djangocfg/nextjs/i18n/routing';
export function generateStaticParams() {
return generateLocaleParams();
}
export default async function LocaleLayout({ children, params }) {
const { locale } = await params;
const messages = await getMessages();
return (
<I18nProvider locale={locale} messages={messages}>
{children}
</I18nProvider>
);
}4. Use translations in components
'use client';
import { useTranslations } from 'next-intl';
function MyComponent() {
const t = useTranslations('app');
return <h1>{t('title')}</h1>;
}Locale Switcher
Smart wrapper around @djangocfg/layouts LocaleSwitcher with automatic next-intl hooks:
import { LocaleSwitcher } from '@djangocfg/nextjs/i18n/components';
// Basic usage (automatically gets locale from next-intl)
<LocaleSwitcher />
// With custom locales (override routing config)
<LocaleSwitcher locales={['en', 'ru']} />
// With custom labels and styling
<LocaleSwitcher
labels={{ en: 'English', ru: 'Русский' }}
variant="outline"
size="sm"
/>Note: This component wraps
@djangocfg/layoutsLocaleSwitcher withuseLocaleSwitcher()hook. For a presentational version that accepts locale data via props, useLocaleSwitcherfrom@djangocfg/layoutsdirectly.
Sitemap Generation
Generate dynamic XML sitemaps with i18n hreflang support:
// app/sitemap.xml/route.ts
import { createSitemapHandler } from '@djangocfg/nextjs/sitemap';
import { routing } from '@djangocfg/nextjs/i18n';
export const GET = createSitemapHandler({
siteUrl: 'https://example.com',
// i18n support with hreflang tags
i18n: {
locales: routing.locales,
defaultLocale: routing.defaultLocale,
},
staticPages: [
{ loc: '/', changefreq: 'daily', priority: 1.0 },
{ loc: '/about', changefreq: 'monthly', priority: 0.8 },
],
dynamicPages: async () => {
const posts = await fetchPosts();
return posts.map(post => ({
loc: `/posts/${post.slug}`,
lastmod: post.updatedAt,
changefreq: 'weekly',
priority: 0.7,
}));
},
});Generated XML with hreflang:
<url>
<loc>https://example.com/en/about</loc>
<xhtml:link rel="alternate" hreflang="en" href="https://example.com/en/about"/>
<xhtml:link rel="alternate" hreflang="ru" href="https://example.com/ru/about"/>
<xhtml:link rel="alternate" hreflang="ko" href="https://example.com/ko/about"/>
<xhtml:link rel="alternate" hreflang="x-default" href="https://example.com/en/about"/>
<changefreq>monthly</changefreq>
<priority>0.8</priority>
</url>Health Check Endpoint
Create a health monitoring endpoint:
// app/api/health/route.ts
import { createHealthHandler } from '@djangocfg/nextjs/health';
export const GET = createHealthHandler({
version: process.env.NEXT_PUBLIC_APP_VERSION || '1.0.0',
checks: [
{
name: 'database',
check: async () => {
// Check database connection
return await checkDatabase();
},
},
],
});OG Image Generation
Builds typed URLs pointing to Django's django_ogimage renderer — no Edge Runtime, no @vercel/og:
// app/page.tsx
import { withOgImage } from '@djangocfg/nextjs/og-image'
export async function generateMetadata(): Promise<Metadata> {
return withOgImage(
{ title: 'My Page', description: 'Description' },
{ preset: 'DARK_BLUE', layout: 'HERO' }
)
}The URL is resolved automatically from NEXT_PUBLIC_MEDIA_URL → NEXT_PUBLIC_API_URL → NEXT_PUBLIC_SITE_URL. Django renders and caches the PNG — no Edge Runtime or @vercel/og required.
Navigation Utilities
Define routes and generate navigation menus:
import { defineRoute, routesToMenuItems } from '@djangocfg/nextjs/navigation';
const routes = [
defineRoute('/dashboard', { title: 'Dashboard' }),
defineRoute('/settings', { title: 'Settings' }),
];
const menuItems = routesToMenuItems(routes);Client Components
Client-side components (legal pages, error pages, redirect components) are available in @djangocfg/layouts:
// Legal pages
import { PrivacyPage, TermsPage } from '@djangocfg/layouts/pages/legal';
// Error pages
import { ErrorLayout } from '@djangocfg/layouts/components/errors';
// Redirect component
import { RedirectPage } from '@djangocfg/layouts/components/RedirectPage';Exports
| Path | Description |
|------|-------------|
| @djangocfg/nextjs | Main exports (all modules) |
| @djangocfg/nextjs/i18n | Types only (safe for server components) |
| @djangocfg/nextjs/i18n/routing | routing, createRouting, generateLocaleParams, DEFAULT_LOCALES, DEFAULT_LOCALE |
| @djangocfg/nextjs/i18n/client | I18nProvider, hooks ('use client') |
| @djangocfg/nextjs/i18n/server | Server-side i18n utilities |
| @djangocfg/nextjs/i18n/components | LocaleSwitcher ('use client') |
| @djangocfg/nextjs/i18n/proxy | createProxy for middleware |
| @djangocfg/nextjs/i18n/navigation | Link, redirect, usePathname, useRouter |
| @djangocfg/nextjs/ai | AI documentation search and MCP config |
| @djangocfg/nextjs/config | Base Next.js configuration factory |
| @djangocfg/nextjs/pwa | PWA client utilities (service worker registration) |
| @djangocfg/nextjs/pwa/worker | Service worker creation helpers |
| @djangocfg/nextjs/sitemap | Sitemap generation with i18n hreflang support |
| @djangocfg/nextjs/health | Health check handlers |
| @djangocfg/nextjs/og-image | OG image URL builder for Django's django_ogimage renderer |
| @djangocfg/nextjs/navigation | Route definitions, menu generation, navigation helpers |
API Reference
Base Configuration
createBaseNextConfig(options)
Creates a reusable base Next.js configuration with standard DjangoCFG settings.
createBaseNextConfig({
basePath?: string; // Base path for static builds
transpilePackages?: string[]; // Additional packages to transpile
optimizePackageImports?: string[]; // Additional packages to optimize
webpack?: (config, options) => config; // Custom webpack configuration
experimental?: NextConfig['experimental']; // Custom experimental options
env?: Record<string, string>; // Custom environment variables
// ... any other NextConfig options
})Features:
- Automatic dev/production optimizations
- Filesystem caching for faster rebuilds
- Compression plugins for static builds (Gzip + Brotli)
- Standard transpile packages for monorepo
- Type-safe configuration merging
i18n
Subpath imports required - see table below for correct import paths.
DEFAULT_LOCALES / DEFAULT_LOCALE
All 17 supported locales and the default locale constant.
import { DEFAULT_LOCALES, DEFAULT_LOCALE } from '@djangocfg/nextjs/i18n/routing';
DEFAULT_LOCALES // ['en', 'ru', 'ko', 'ja', 'de', 'fr', 'zh', 'it', 'es', 'nl', 'ar', 'tr', 'pt-BR', 'pl', 'sv', 'no', 'da']
DEFAULT_LOCALE // 'en'Use in locales.config.ts to stay in sync with the package:
// i18n/locales.config.ts
export { DEFAULT_LOCALES as LOCALES, DEFAULT_LOCALE } from '@djangocfg/nextjs/i18n/routing';
export type { LocaleCode as AppLocale } from '@djangocfg/nextjs/i18n';routing
Default routing configuration with all 17 locales and default locale 'en'.
import { routing } from '@djangocfg/nextjs/i18n/routing';
routing.locales // ['en', 'ru', 'ko', 'ja', ...]
routing.defaultLocale // 'en'createRouting(config?)
Create custom routing configuration.
import { createRouting } from '@djangocfg/nextjs/i18n/routing';
const routing = createRouting({
locales: ['en', 'de', 'fr'],
defaultLocale: 'en',
localePrefix: 'always', // 'always' | 'as-needed' | 'never'
});I18nProvider
Provider component for next-intl integration (client component).
import { I18nProvider } from '@djangocfg/nextjs/i18n/client';
<I18nProvider locale="en" messages={messages}>
{children}
</I18nProvider>LocaleSwitcher
Smart locale switcher that wraps @djangocfg/layouts LocaleSwitcher with next-intl hooks.
import { LocaleSwitcher } from '@djangocfg/nextjs/i18n/components';
// Automatically gets locale from next-intl routing
<LocaleSwitcher />
// With custom options
<LocaleSwitcher
locales={['en', 'ru']} // Override available locales
labels={{ en: 'EN', ru: 'RU' }} // Custom locale labels
variant="outline"
size="sm"
showIcon={true}
className="w-full"
/>Props (extends @djangocfg/layouts LocaleSwitcherProps):
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| locales | string[] | From routing | Override available locales |
| labels | Record<string, string> | Built-in | Custom locale labels |
| showCode | boolean | false | Show locale code with label |
| variant | 'ghost' \| 'outline' \| 'default' | 'ghost' | Button variant |
| size | 'sm' \| 'default' \| 'lg' \| 'icon' | 'sm' | Button size |
| showIcon | boolean | true | Show globe icon |
Sitemap
createSitemapHandler(options)
Creates a Next.js route handler for sitemap generation with optional i18n support.
createSitemapHandler({
siteUrl: string;
staticPages?: SitemapUrl[];
dynamicPages?: SitemapUrl[] | (() => Promise<SitemapUrl[]>);
cacheControl?: string;
// i18n support
i18n?: {
locales: string[]; // e.g., ['en', 'ru', 'ko']
defaultLocale: string; // e.g., 'en'
};
})When i18n is provided:
- URLs are expanded for each locale (e.g.,
/about→/en/about,/ru/about,/ko/about) xhtml:linkelements withhreflangare added for SEOx-defaultpoints to the default locale
Health
createHealthHandler(config)
Creates a health check route handler.
createHealthHandler({
version?: string;
checks?: Array<{ name: string; check: () => Promise<boolean> }>;
customData?: Record<string, any>;
})OG Image
@djangocfg/nextjs/og-image builds typed URLs pointing to Django's django_ogimage renderer.
No Edge Runtime, no @vercel/og, no JSX templates — Django renders and caches the PNG.
See src/og-image/README.md for full docs including URL resolution logic and deployment examples.
withOgImage(metadata, params)
Merges OG image into an existing Metadata object. Auto-extracts title if not in params.
import { withOgImage } from '@djangocfg/nextjs/og-image'
export async function generateMetadata(): Promise<Metadata> {
return withOgImage(
{ title: 'My Page', description: 'Description' },
{ preset: 'DARK_BLUE', layout: 'HERO' }
)
}createOgMetadata(params)
Returns a Metadata fragment with openGraph.images + twitter.images.
import { createOgMetadata } from '@djangocfg/nextjs/og-image'
export async function generateMetadata() {
return createOgMetadata({ title: 'Page', preset: 'DARK_BLUE' })
}buildOgUrl(params)
Returns the raw URL string. Useful when you need the URL outside of metadata.
import { buildOgUrl } from '@djangocfg/nextjs/og-image'
const url = buildOgUrl({ title: 'Hello', preset: 'DARK_BLUE' })URL resolution (NEXT_PUBLIC_MEDIA_URL → NEXT_PUBLIC_API_URL → NEXT_PUBLIC_SITE_URL → relative).
Navigation
defineRoute(path, metadata, config?)
Defines a route with metadata.
defineRoute('/dashboard', {
title: 'Dashboard',
description: 'Dashboard overview',
}, {
basePath: '/admin',
isStaticBuild: false,
})isActive(current, target, allRoutes?)
Checks if a route is currently active.
isActive('/admin/dashboard', '/admin/dashboard') // true
isActive('/admin/dashboard/settings', '/admin/dashboard') // true
isActive('/admin/dashboard', '/admin/settings') // falseroutesToMenuItems(routes)
Converts route definitions to menu items.
const menuItems = routesToMenuItems(allRoutes);Requirements
- Next.js >= 13.0.0 (App Router)
- React >= 18.0.0
- TypeScript >= 5.0.0
Peer Dependencies
next- Next.js framework (^15.5.7)
Documentation
Full documentation available at djangocfg.com
Contributing
Issues and pull requests are welcome at GitHub
License
MIT - see LICENSE for details
