npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@djangocfg/nextjs

v2.1.466

Published

Next.js server utilities: sitemap, health, OG images, contact forms, navigation, config

Readme

@djangocfg/nextjs

@djangocfg/nextjs

Server-side Next.js utilities: OG images, sitemap, health checks, i18n, PWA, navigation, and config

npm version License: MIT

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

  • Page Metadata + OG Images — one factory for complete page metadata; static or dynamically-rendered OG images via Django's django_ogimage (@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
  • Security headers + CSP — baseline Content-Security-Policy and hardening headers on every route, dev-aware (see below)
  • DPoP auth — one-flag opt-in to RFC 9449 sender-constrained tokens (dpop: true) — see @docs/DPOP.md
  • Sitemap — paginated sitemap-index backed by django_cfg.modules.django_sitemap (handles 2M+ URLs)
  • 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/nextjs

Quick 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 mcp

Or 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;
  },
}));

Security headers & CSP

createBaseNextConfig() adds baseline security headers to every route out of the box — no setup required:

  • Content-Security-Policy — a pragmatic baseline that blocks the high-value injection vectors (object-src 'none', base-uri 'self', form-action 'self', frame-ancestors) while keeping the inline/eval scripts a Next.js app needs. Dev-aware: connect-src/img-src allow http:/ws: in development (local Django/Centrifugo) and tighten to https:/wss: only in production.
  • X-Content-Type-Options: nosniff, Referrer-Policy: strict-origin-when-cross-origin
  • X-Frame-Options: DENY (or SAMEORIGIN when allowIframeFrom is set)

A fully strict nonce-based script-src is a planned follow-up (needs middleware + per-request nonce). To allow iframe embedding, pass allowIframeFrom: ['https://example.com'].

DPoP — sender-constrained tokens (RFC 9449)

Make a stolen access token useless, without a BFF/proxy — opt in with one flag:

export default createBaseNextConfig({
  dpop: true, // inlines NEXT_PUBLIC_DPOP_ENABLED='true'
});

The browser holds a non-extractable key and signs a per-request DPoP proof; the backend binds the token to that key (cnf.jkt) and rejects replays. Requires JWTConfig(dpop_enabled=True) on the Django side. Full guide: @docs/DPOP.md.

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 - From app/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/layouts LocaleSwitcher with useLocaleSwitcher() hook. For a presentational version that accepts locale data via props, use LocaleSwitcher from @djangocfg/layouts directly.

Sitemap Generation

Paginated sitemap-index integrated with django_cfg.modules.django_sitemap. Backed by a typed JSON contract: Django streams keyset-paginated chunks, Next.js's native generateSitemaps() turns each chunk into one XML file plus an auto-generated <sitemapindex> at /sitemap.xml. Handles catalogs up to Google's 50 000-URLs-per-file cap without materialising data on the frontend.

// app/sitemap.ts
import { createDjangoSitemap } from '@djangocfg/nextjs/sitemap';

const { generateSitemaps, sitemap } = createDjangoSitemap({
  host: process.env.NEXT_PUBLIC_SITE_URL!,
  apiUrl: process.env.NEXT_PUBLIC_API_URL,  // optional — omit for static-only
  staticRoutes: [
    { path: '/', changeFrequency: 'daily', priority: 1.0 },
    { path: '/catalog', changeFrequency: 'daily', priority: 0.9 },
  ],
});

export { generateSitemaps, sitemap as default };
export const revalidate = 3600;
// app/robots.ts
import { createRobots } from '@djangocfg/nextjs/sitemap';

export default createRobots({
  host: process.env.NEXT_PUBLIC_SITE_URL!,
  disallow: ['/account/', '/auth', '/api/'],
});

See src/sitemap/README.md for the full backend ↔ frontend integration guide, including the Django source registration, cache layers, and deployment notes.

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();
      },
    },
  ],
});

Page Metadata + OG Images

One factory per app builds complete page Metadata (title, openGraph, twitter, canonical + hreflang, icons). The OG image is chosen by a single og field — static brand image by default, dynamic title-rendered card on demand. No Edge Runtime, no @vercel/og:

// app/_core/metadata.ts — bind once
import { makeMetadataFactory } from '@djangocfg/nextjs/og-image'
export const createMetadata = makeMetadataFactory({
  name: settings.app.name,
  description: settings.app.description,
  siteUrl: settings.app.siteUrl,
  ogImage: settings.app.media.ogimage,
  locales: LOCALES,
})

// landing page → static brand image (default)
export const metadata = createMetadata({ title: 'Pricing', path: '/pricing' })
// content page → render the title onto the card
export const metadata = createMetadata({ title: post.title, path, og: 'dynamic' })

The dynamic URL is resolved automatically from NEXT_PUBLIC_MEDIA_URLNEXT_PUBLIC_API_URLNEXT_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 | Page metadata factory + static/dynamic OG images for Django's django_ogimage | | @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:link elements with hreflang are added for SEO
  • x-default points 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>;
})

Page Metadata + OG Image

@djangocfg/nextjs/og-image builds complete page metadata and OG images for 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 (the og axis, SiteMetaConfig/PageMeta fields, URL resolution, deployment examples).

makeMetadataFactory(config) — recommended

Binds a SiteMetaConfig once; returns a per-page factory. The OG image is set by the single og field: 'static' (default) · 'dynamic' · { render } · { image, alt? }.

import { makeMetadataFactory } from '@djangocfg/nextjs/og-image'

export const createMetadata = makeMetadataFactory({
  name: 'CMDOP', description: '…', siteUrl: 'https://cmdop.com',
  ogImage: '/static/ogimage.png', locales: LOCALES,
})

export const metadata = createMetadata({ title: 'About', path: '/about' })          // static
export const metadata = createMetadata({ title: post.title, path, og: 'dynamic' })  // rendered title

Low-level (escape hatches)

withOgImage(metadata, params) merges a dynamic OG image into existing metadata; createOgMetadata(params) returns the { openGraph, twitter } fragment; buildOgUrl(params) returns the raw URL string; resolveOgImage(spec, …) is the OgSpec decision point. Most pages use createMetadata and never touch these.

import { buildOgUrl } from '@djangocfg/nextjs/og-image'
const url = buildOgUrl({ title: 'Hello', preset: 'DARK_BLUE' })

URL resolution (NEXT_PUBLIC_MEDIA_URLNEXT_PUBLIC_API_URLNEXT_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') // false

routesToMenuItems(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