@djangocfg/nextjs 2.1.1 → 2.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -18,6 +18,7 @@
18
18
  ## Features
19
19
 
20
20
  - **Base Next.js Config** - Universal, reusable Next.js configuration factory for monorepos
21
+ - **AI Documentation** - Search DjangoCFG docs via MCP server and CLI
21
22
  - **Sitemap Generation** - Dynamic XML sitemap generation for SEO
22
23
  - **Health Checks** - Production-ready health monitoring endpoints
23
24
  - **OG Images** - Dynamic Open Graph image generation with templates
@@ -38,6 +39,46 @@ yarn add @djangocfg/nextjs
38
39
 
39
40
  ## Quick Start
40
41
 
42
+ ### AI Documentation Search
43
+
44
+ Search DjangoCFG documentation from the terminal:
45
+
46
+ ```bash
47
+ # CLI
48
+ pnpm ai-docs search "database configuration"
49
+ pnpm ai-docs mcp
50
+ ```
51
+
52
+ Or use the TypeScript API:
53
+
54
+ ```tsx
55
+ import { search, getDocs, getMcpConfig } from '@djangocfg/nextjs/ai';
56
+
57
+ // Search documentation
58
+ const results = await search('database configuration');
59
+ results.forEach(r => console.log(r.title, r.url));
60
+
61
+ // Get formatted docs
62
+ const docs = await getDocs('How to configure PostgreSQL?');
63
+
64
+ // Get MCP server config for AI assistants
65
+ const config = getMcpConfig();
66
+ ```
67
+
68
+ ### MCP Server for AI Assistants
69
+
70
+ Add to your AI assistant configuration:
71
+
72
+ ```json
73
+ {
74
+ "mcpServers": {
75
+ "djangocfg-docs": {
76
+ "url": "https://mcp.djangocfg.com/mcp"
77
+ }
78
+ }
79
+ }
80
+ ```
81
+
41
82
  ### Base Next.js Configuration
42
83
 
43
84
  Create a reusable base configuration for all your Next.js projects:
@@ -203,6 +244,7 @@ import { RedirectPage } from '@djangocfg/layouts/components/RedirectPage';
203
244
  | Path | Description |
204
245
  |------|-------------|
205
246
  | `@djangocfg/nextjs` | Main exports (all modules) |
247
+ | `@djangocfg/nextjs/ai` | AI documentation search and MCP config |
206
248
  | `@djangocfg/nextjs/config` | Base Next.js configuration factory |
207
249
  | `@djangocfg/nextjs/sitemap` | Sitemap generation utilities |
208
250
  | `@djangocfg/nextjs/health` | Health check handlers |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@djangocfg/nextjs",
3
- "version": "2.1.1",
3
+ "version": "2.1.3",
4
4
  "description": "Next.js server utilities: sitemap, health, OG images, contact forms, navigation, config",
5
5
  "keywords": [
6
6
  "nextjs",
@@ -79,6 +79,11 @@
79
79
  "types": "./src/scripts/index.ts",
80
80
  "import": "./src/scripts/index.ts",
81
81
  "default": "./src/scripts/index.ts"
82
+ },
83
+ "./ai": {
84
+ "types": "./src/ai/index.ts",
85
+ "import": "./src/ai/index.ts",
86
+ "default": "./src/ai/index.ts"
82
87
  }
83
88
  },
84
89
  "files": [
@@ -86,22 +91,26 @@
86
91
  "README.md",
87
92
  "LICENSE"
88
93
  ],
94
+ "bin": {
95
+ "ai-docs": "./src/ai/cli.ts"
96
+ },
89
97
  "scripts": {
90
98
  "build": "tsup",
91
99
  "dev": "tsup --watch",
92
100
  "clean": "rm -rf dist",
93
101
  "lint": "eslint .",
94
102
  "check": "tsc --noEmit",
95
- "check-links": "tsx src/scripts/check-links.ts"
103
+ "check-links": "tsx src/scripts/check-links.ts",
104
+ "ai-docs": "tsx src/ai/cli.ts"
96
105
  },
97
106
  "peerDependencies": {
98
- "@djangocfg/api": "^2.1.1",
107
+ "@djangocfg/api": "^2.1.3",
99
108
  "next": "^15.5.7"
100
109
  },
101
110
  "devDependencies": {
102
- "@djangocfg/imgai": "^2.1.1",
103
- "@djangocfg/layouts": "^2.1.1",
104
- "@djangocfg/typescript-config": "^2.1.1",
111
+ "@djangocfg/imgai": "^2.1.3",
112
+ "@djangocfg/layouts": "^2.1.3",
113
+ "@djangocfg/typescript-config": "^2.1.3",
105
114
  "@types/node": "^24.7.2",
106
115
  "@types/react": "19.2.2",
107
116
  "@types/react-dom": "19.2.1",
@@ -0,0 +1,48 @@
1
+ # @djangocfg/nextjs - AI Documentation
2
+
3
+ DjangoCFG documentation is available via MCP server.
4
+
5
+ ## MCP Server
6
+
7
+ ```json
8
+ {
9
+ "mcpServers": {
10
+ "djangocfg-docs": {
11
+ "url": "https://mcp.djangocfg.com/mcp"
12
+ }
13
+ }
14
+ }
15
+ ```
16
+
17
+ ## API
18
+
19
+ ```bash
20
+ curl 'https://mcp.djangocfg.com/api/search?q=database+configuration&limit=5'
21
+ ```
22
+
23
+ ## TypeScript
24
+
25
+ ```ts
26
+ import { search, getDocs, getMcpConfig } from '@djangocfg/nextjs/ai';
27
+
28
+ // Search documentation
29
+ const results = await search('database configuration');
30
+ results.forEach(r => console.log(r.title, r.url));
31
+
32
+ // Get formatted docs
33
+ const docs = await getDocs('How to configure PostgreSQL?');
34
+
35
+ // Get MCP config
36
+ const config = getMcpConfig();
37
+ ```
38
+
39
+ ## Common Topics
40
+
41
+ - DatabaseConfig - PostgreSQL, MySQL, SQLite
42
+ - CacheConfig - Redis, Memcached
43
+ - EmailConfig - SMTP, SendGrid
44
+ - LoggingConfig - Logging setup
45
+ - SecurityConfig - CORS, CSRF
46
+ - DRFConfig - Django REST Framework
47
+ - OG Image - Open Graph image generation
48
+ - Sitemap - XML sitemap generation
package/src/ai/cli.ts ADDED
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * DjangoCFG AI Docs CLI
4
+ *
5
+ * Usage:
6
+ * pnpm exec ai-docs search "database configuration"
7
+ * pnpm exec ai-docs mcp
8
+ * npx @djangocfg/nextjs ai-docs search "query"
9
+ */
10
+
11
+ import { search, getMcpConfig, MCP_SERVER_URL, MCP_API_URL } from './index';
12
+
13
+ const args = process.argv.slice(2);
14
+ const command = args[0];
15
+ const query = args.slice(1).join(' ');
16
+
17
+ async function main() {
18
+ switch (command) {
19
+ case 'search':
20
+ case 's':
21
+ if (!query) {
22
+ console.error('Usage: ai-docs search "your query"');
23
+ process.exit(1);
24
+ }
25
+ console.log(`\n🔍 Searching: ${query}\n`);
26
+ try {
27
+ const results = await search(query, { limit: 5 });
28
+ if (results.length === 0) {
29
+ console.log('No results found.');
30
+ } else {
31
+ results.forEach((r, i) => {
32
+ console.log(`${i + 1}. ${r.title}`);
33
+ console.log(` ${r.content.slice(0, 150)}...`);
34
+ if (r.url) console.log(` 📖 ${r.url}`);
35
+ console.log('');
36
+ });
37
+ }
38
+ } catch (err) {
39
+ console.error('Error:', err instanceof Error ? err.message : err);
40
+ process.exit(1);
41
+ }
42
+ break;
43
+
44
+ case 'mcp':
45
+ console.log('\n📡 MCP Server Configuration:\n');
46
+ console.log(JSON.stringify(getMcpConfig(), null, 2));
47
+ console.log('\nAdd this to your AI assistant configuration.');
48
+ break;
49
+
50
+ case 'info':
51
+ case 'i':
52
+ console.log('\n🤖 DjangoCFG AI Documentation\n');
53
+ console.log(`MCP Server: ${MCP_SERVER_URL}`);
54
+ console.log(`Search API: ${MCP_API_URL}`);
55
+ console.log('\nUsage:');
56
+ console.log(' pnpm exec ai-docs search "database configuration"');
57
+ console.log(' pnpm exec ai-docs mcp');
58
+ break;
59
+
60
+ default:
61
+ console.log('🤖 DjangoCFG AI Documentation CLI\n');
62
+ console.log('Commands:');
63
+ console.log(' search <query> Search documentation');
64
+ console.log(' mcp Show MCP server config');
65
+ console.log(' info Show help\n');
66
+ console.log('Examples:');
67
+ console.log(' pnpm exec ai-docs search "database configuration"');
68
+ console.log(' pnpm exec ai-docs search "redis cache"');
69
+ console.log(' pnpm exec ai-docs mcp');
70
+ break;
71
+ }
72
+ }
73
+
74
+ main();
@@ -0,0 +1,171 @@
1
+ /**
2
+ * DjangoCFG Documentation Client
3
+ *
4
+ * HTTP client for accessing DjangoCFG documentation via MCP server API.
5
+ */
6
+
7
+ import {
8
+ MCP_BASE_URL,
9
+ API_SEARCH_ENDPOINT,
10
+ API_INFO_ENDPOINT,
11
+ DEFAULT_TIMEOUT,
12
+ } from './constants';
13
+ import type { SearchResult, SearchOptions, McpConfig, ApiSearchResponse } from './types';
14
+
15
+ /**
16
+ * Client for DjangoCFG Documentation API.
17
+ */
18
+ export class DjangoCfgDocsClient {
19
+ private baseUrl: string;
20
+ private timeout: number;
21
+
22
+ constructor(baseUrl: string = MCP_BASE_URL, timeout: number = DEFAULT_TIMEOUT) {
23
+ this.baseUrl = baseUrl.replace(/\/$/, '');
24
+ this.timeout = timeout;
25
+ }
26
+
27
+ private async makeRequest<T>(endpoint: string, params?: Record<string, string | number>): Promise<T> {
28
+ let url = `${this.baseUrl}${endpoint}`;
29
+
30
+ if (params) {
31
+ const searchParams = new URLSearchParams();
32
+ for (const [key, value] of Object.entries(params)) {
33
+ searchParams.set(key, String(value));
34
+ }
35
+ url = `${url}?${searchParams.toString()}`;
36
+ }
37
+
38
+ const controller = new AbortController();
39
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
40
+
41
+ try {
42
+ const response = await fetch(url, {
43
+ method: 'GET',
44
+ headers: {
45
+ Accept: 'application/json',
46
+ 'User-Agent': 'DjangoCFG-AI-Client/1.0',
47
+ },
48
+ signal: controller.signal,
49
+ });
50
+
51
+ if (!response.ok) {
52
+ throw new Error(`HTTP Error ${response.status}: ${response.statusText}`);
53
+ }
54
+
55
+ return await response.json();
56
+ } finally {
57
+ clearTimeout(timeoutId);
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Search documentation.
63
+ */
64
+ async search(query: string, options: SearchOptions = {}): Promise<SearchResult[]> {
65
+ const { limit = 5, category } = options;
66
+
67
+ const params: Record<string, string | number> = { q: query, limit };
68
+ if (category) {
69
+ params.category = category;
70
+ }
71
+
72
+ const data = await this.makeRequest<ApiSearchResponse>(API_SEARCH_ENDPOINT, params);
73
+
74
+ const results = data.results || (Array.isArray(data) ? data : []);
75
+
76
+ return results.map((item) => ({
77
+ title: item.title || '',
78
+ content: item.content || item.snippet || '',
79
+ url: item.url || '',
80
+ score: item.score || 0,
81
+ category: item.category || '',
82
+ }));
83
+ }
84
+
85
+ /**
86
+ * Get detailed info about a specific topic.
87
+ */
88
+ async getInfo(topic: string): Promise<Record<string, unknown>> {
89
+ return this.makeRequest(API_INFO_ENDPOINT, { topic });
90
+ }
91
+
92
+ /**
93
+ * Get MCP server configuration for AI assistants.
94
+ */
95
+ getMcpConfig(): McpConfig {
96
+ return {
97
+ mcpServers: {
98
+ 'djangocfg-docs': {
99
+ url: `${this.baseUrl}/mcp`,
100
+ },
101
+ },
102
+ };
103
+ }
104
+ }
105
+
106
+ // Default client instance
107
+ let defaultClient: DjangoCfgDocsClient | null = null;
108
+
109
+ function getClient(): DjangoCfgDocsClient {
110
+ if (!defaultClient) {
111
+ defaultClient = new DjangoCfgDocsClient();
112
+ }
113
+ return defaultClient;
114
+ }
115
+
116
+ /**
117
+ * Search DjangoCFG documentation.
118
+ *
119
+ * @example
120
+ * ```ts
121
+ * const results = await search('database configuration');
122
+ * results.forEach(r => console.log(r.title, r.url));
123
+ * ```
124
+ */
125
+ export async function search(query: string, options: SearchOptions = {}): Promise<SearchResult[]> {
126
+ return getClient().search(query, options);
127
+ }
128
+
129
+ /**
130
+ * Get documentation as formatted text.
131
+ *
132
+ * @example
133
+ * ```ts
134
+ * const docs = await getDocs('How to configure PostgreSQL?');
135
+ * console.log(docs);
136
+ * ```
137
+ */
138
+ export async function getDocs(query: string, limit: number = 3): Promise<string> {
139
+ const results = await search(query, { limit });
140
+
141
+ if (results.length === 0) {
142
+ return `No documentation found for: ${query}`;
143
+ }
144
+
145
+ const output: string[] = [];
146
+
147
+ results.forEach((r, i) => {
148
+ output.push(`## ${i + 1}. ${r.title}`);
149
+ output.push(r.content);
150
+ if (r.url) {
151
+ output.push(`📖 Read more: ${r.url}`);
152
+ }
153
+ output.push('');
154
+ });
155
+
156
+ return output.join('\n');
157
+ }
158
+
159
+ /**
160
+ * Get detailed info about a topic.
161
+ */
162
+ export async function getInfo(topic: string): Promise<Record<string, unknown>> {
163
+ return getClient().getInfo(topic);
164
+ }
165
+
166
+ /**
167
+ * Get MCP server configuration.
168
+ */
169
+ export function getMcpConfig(): McpConfig {
170
+ return getClient().getMcpConfig();
171
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * AI Documentation Constants
3
+ */
4
+
5
+ // MCP Server URLs
6
+ export const MCP_BASE_URL = 'https://mcp.djangocfg.com';
7
+ export const MCP_SERVER_URL = `${MCP_BASE_URL}/mcp`;
8
+ export const MCP_API_URL = `${MCP_BASE_URL}/api/search`;
9
+
10
+ // API Endpoints
11
+ export const API_SEARCH_ENDPOINT = '/api/search';
12
+ export const API_INFO_ENDPOINT = '/api/info';
13
+ export const DEFAULT_TIMEOUT = 10000; // ms
14
+
15
+ // AI Hint for console output
16
+ export const AI_DOCS_HINT = `🤖 AI Docs: ${MCP_SERVER_URL} | pnpm ai-docs search "query"`;
17
+
18
+ // Full AI Hint description
19
+ export const AI_HINT = `
20
+ DjangoCFG Documentation is available via MCP server.
21
+
22
+ To get help with DjangoCFG configuration:
23
+ 1. Use the MCP server: ${MCP_SERVER_URL}
24
+ 2. Or search directly: ${MCP_API_URL}?q=YOUR_QUERY&limit=5
25
+
26
+ Example queries:
27
+ - "How to configure PostgreSQL database?"
28
+ - "What is DatabaseConfig?"
29
+ - "How to setup Redis cache?"
30
+ - "Email configuration with SMTP"
31
+ `;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * DjangoCFG AI Documentation Client
3
+ *
4
+ * Provides access to DjangoCFG documentation via MCP server API.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * import { search, getDocs, getMcpConfig } from '@djangocfg/nextjs/ai';
9
+ *
10
+ * // Search documentation
11
+ * const results = await search('database configuration');
12
+ *
13
+ * // Get formatted docs
14
+ * const docs = await getDocs('How to configure PostgreSQL?');
15
+ *
16
+ * // Get MCP config for AI assistants
17
+ * const config = getMcpConfig();
18
+ * ```
19
+ */
20
+
21
+ export { DjangoCfgDocsClient, search, getDocs, getInfo, getMcpConfig } from './client';
22
+ export type { SearchResult, SearchOptions, McpConfig } from './types';
23
+ export {
24
+ MCP_BASE_URL,
25
+ MCP_SERVER_URL,
26
+ MCP_API_URL,
27
+ AI_DOCS_HINT,
28
+ AI_HINT,
29
+ } from './constants';
@@ -0,0 +1,35 @@
1
+ /**
2
+ * AI Documentation Types
3
+ */
4
+
5
+ export interface SearchResult {
6
+ title: string;
7
+ content: string;
8
+ url: string;
9
+ score: number;
10
+ category: string;
11
+ }
12
+
13
+ export interface SearchOptions {
14
+ limit?: number;
15
+ category?: string;
16
+ }
17
+
18
+ export interface McpConfig {
19
+ mcpServers: {
20
+ 'djangocfg-docs': {
21
+ url: string;
22
+ };
23
+ };
24
+ }
25
+
26
+ export interface ApiSearchResponse {
27
+ results: Array<{
28
+ title: string;
29
+ content?: string;
30
+ snippet?: string;
31
+ url: string;
32
+ score?: number;
33
+ category?: string;
34
+ }>;
35
+ }
@@ -24,6 +24,14 @@ export {
24
24
  DJANGO_CFG_BANNER,
25
25
  } from './constants';
26
26
 
27
+ // Re-export AI constants from ai module
28
+ export {
29
+ MCP_BASE_URL,
30
+ MCP_SERVER_URL,
31
+ MCP_API_URL,
32
+ AI_DOCS_HINT,
33
+ } from '../ai/constants';
34
+
27
35
  // Utils
28
36
  export { deepMerge } from './utils/deepMerge';
29
37
  export {
@@ -300,11 +300,12 @@ async function updateSinglePackage(
300
300
 
301
301
  spinner.start();
302
302
 
303
+ // Always install with @latest to keep package.json consistent
303
304
  const command = pm === 'pnpm'
304
- ? `pnpm add ${pkg.name}@${pkg.latest}`
305
+ ? `pnpm add ${pkg.name}@latest`
305
306
  : pm === 'yarn'
306
- ? `yarn add ${pkg.name}@${pkg.latest}`
307
- : `npm install ${pkg.name}@${pkg.latest}`;
307
+ ? `yarn add ${pkg.name}@latest`
308
+ : `npm install ${pkg.name}@latest`;
308
309
 
309
310
  return new Promise((resolve) => {
310
311
  const proc = spawn(command, {
@@ -7,6 +7,7 @@
7
7
  import type { Compiler } from 'webpack';
8
8
  import chalk from 'chalk';
9
9
  import { DJANGO_CFG_BANNER } from '../constants';
10
+ import { AI_DOCS_HINT } from '../../ai/constants';
10
11
  import { getCurrentVersion } from '../utils/version';
11
12
  import { checkAndInstallPackages } from '../packages/installer';
12
13
  import { checkAndUpdatePackages } from '../packages/updater';
@@ -64,10 +65,13 @@ export class DevStartupPlugin {
64
65
  // 2. Print current version
65
66
  const version = getCurrentVersion();
66
67
  if (version) {
67
- console.log(chalk.dim(` 📦 @djangocfg/nextjs v${version}\n`));
68
+ console.log(chalk.dim(` 📦 @djangocfg/nextjs v${version}`));
68
69
  }
69
70
 
70
- // 3. Check for package updates
71
+ // 3. Print AI docs hint
72
+ console.log(chalk.magenta(` ${AI_DOCS_HINT}\n`));
73
+
74
+ // 4. Check for package updates
71
75
  if (this.options.checkUpdates !== false) {
72
76
  try {
73
77
  await checkAndUpdatePackages({
@@ -80,7 +84,7 @@ export class DevStartupPlugin {
80
84
  }
81
85
  }
82
86
 
83
- // 4. Check for missing optional packages
87
+ // 5. Check for missing optional packages
84
88
  if (this.options.checkPackages !== false) {
85
89
  await checkAndInstallPackages({
86
90
  autoInstall: this.options.autoInstall,
package/src/index.ts CHANGED
@@ -22,6 +22,9 @@ export * from './navigation';
22
22
  // Config
23
23
  export * from './config';
24
24
 
25
+ // AI Documentation
26
+ export * from './ai';
27
+
25
28
  // Types
26
29
  export type * from './types';
27
30