django-cfg 1.4.92__py3-none-any.whl → 1.4.94__py3-none-any.whl

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.

Potentially problematic release.


This version of django-cfg might be problematic. Click here for more details.

django_cfg/__init__.py CHANGED
@@ -32,7 +32,7 @@ Example:
32
32
  default_app_config = "django_cfg.apps.DjangoCfgConfig"
33
33
 
34
34
  # Version information
35
- __version__ = "1.4.92"
35
+ __version__ = "1.4.94"
36
36
  __license__ = "MIT"
37
37
 
38
38
  # Import registry for organized lazy loading
@@ -4,14 +4,17 @@ JWT tokens are automatically injected into HTML responses for authenticated user
4
4
  This is specific to Next.js frontend apps only.
5
5
 
6
6
  Features:
7
- - Automatic extraction of ZIP archives on first request
7
+ - Automatic extraction of ZIP archives with smart update detection
8
+ - Auto-reextraction when ZIP is modified within last 5 minutes
8
9
  - SPA routing with fallback strategies
9
10
  - JWT token injection for authenticated users
10
11
  """
11
12
 
12
13
  import logging
13
14
  import zipfile
15
+ import shutil
14
16
  from pathlib import Path
17
+ from datetime import datetime, timedelta
15
18
  from django.http import Http404, HttpResponse, FileResponse
16
19
  from django.views.static import serve
17
20
  from django.views import View
@@ -23,19 +26,101 @@ from rest_framework_simplejwt.tokens import RefreshToken
23
26
  logger = logging.getLogger(__name__)
24
27
 
25
28
 
29
+ class ZipExtractionMixin:
30
+ """
31
+ Mixin for automatic ZIP extraction with age-based refresh.
32
+
33
+ Provides intelligent ZIP archive handling:
34
+ - Auto-extraction when directory doesn't exist
35
+ - Auto-reextraction when extracted directory is older than 10 minutes
36
+ - Simple age-based logic (no ZIP timestamp comparison needed)
37
+
38
+ Usage:
39
+ class MyView(ZipExtractionMixin, View):
40
+ app_name = 'myapp' # Will look for myapp.zip
41
+ """
42
+
43
+ # Maximum age of extracted directory before re-extraction (in seconds)
44
+ MAX_DIRECTORY_AGE = 600 # 10 minutes = 600 seconds
45
+
46
+ def extract_zip_if_needed(self, base_dir: Path, zip_path: Path, app_name: str) -> bool:
47
+ """
48
+ Extract ZIP archive if needed based on directory age.
49
+
50
+ Args:
51
+ base_dir: Target directory for extraction
52
+ zip_path: Path to ZIP archive
53
+ app_name: Name of the app (for logging)
54
+
55
+ Returns:
56
+ bool: True if extraction succeeded or not needed, False if failed
57
+ """
58
+ should_extract = False
59
+
60
+ # Priority 1: If directory doesn't exist at all - always extract
61
+ if not base_dir.exists():
62
+ should_extract = True
63
+ logger.info(f"[{app_name}] Directory doesn't exist, will extract")
64
+
65
+ # Priority 2: Directory exists - check if it's too old
66
+ else:
67
+ # Get directory modification time
68
+ dir_mtime = datetime.fromtimestamp(base_dir.stat().st_mtime)
69
+ directory_age = (datetime.now() - dir_mtime).total_seconds()
70
+
71
+ # If directory is older than MAX_DIRECTORY_AGE - re-extract
72
+ if directory_age > self.MAX_DIRECTORY_AGE:
73
+ logger.info(f"[{app_name}] Directory is old ({directory_age:.0f}s > {self.MAX_DIRECTORY_AGE}s), re-extracting")
74
+ try:
75
+ shutil.rmtree(base_dir)
76
+ should_extract = True
77
+ except Exception as e:
78
+ logger.error(f"[{app_name}] Failed to remove old directory: {e}")
79
+ return False
80
+ else:
81
+ logger.debug(f"[{app_name}] Directory is fresh ({directory_age:.0f}s), using existing")
82
+
83
+ # Extract ZIP if needed
84
+ if should_extract:
85
+ if zip_path.exists():
86
+ logger.info(f"[{app_name}] Extracting {zip_path.name} to {base_dir}...")
87
+ try:
88
+ base_dir.parent.mkdir(parents=True, exist_ok=True)
89
+ with zipfile.ZipFile(zip_path, 'r') as zip_ref:
90
+ zip_ref.extractall(base_dir)
91
+ logger.info(f"[{app_name}] Successfully extracted {zip_path.name}")
92
+ return True
93
+ except Exception as e:
94
+ logger.error(f"[{app_name}] Failed to extract: {e}")
95
+ return False
96
+ else:
97
+ logger.error(f"[{app_name}] ZIP not found: {zip_path}")
98
+ return False
99
+
100
+ # Directory exists and is fresh
101
+ return True
102
+
103
+
26
104
  @method_decorator(xframe_options_exempt, name='dispatch')
27
- class NextJSStaticView(View):
105
+ class NextJSStaticView(ZipExtractionMixin, View):
28
106
  """
29
107
  Serve Next.js static build files with automatic JWT token injection.
30
108
 
31
109
  Features:
32
110
  - Serves Next.js static export files like a static file server
111
+ - Smart ZIP extraction: auto-refreshes when directory older than 10 minutes
33
112
  - Automatically injects JWT tokens for authenticated users
34
113
  - Tokens injected into HTML responses only
35
114
  - Handles Next.js client-side routing (.html fallback)
36
115
  - Automatically serves index.html for directory paths
37
116
  - X-Frame-Options exempt to allow embedding in iframes
38
117
 
118
+ ZIP Extraction Logic:
119
+ - If directory doesn't exist: extract from ZIP
120
+ - If directory older than 10 minutes: remove and re-extract
121
+ - If directory fresh (< 10 min): use existing files
122
+ - This enables auto-refresh during development while caching in production
123
+
39
124
  Path resolution examples:
40
125
  - /cfg/admin/ → /cfg/admin/index.html
41
126
  - /cfg/admin/private/ → /cfg/admin/private/index.html (if exists)
@@ -51,22 +136,16 @@ class NextJSStaticView(View):
51
136
  import django_cfg
52
137
 
53
138
  base_dir = Path(django_cfg.__file__).parent / 'static' / 'frontend' / self.app_name
139
+ zip_path = Path(django_cfg.__file__).parent / 'static' / 'frontend' / f'{self.app_name}.zip'
54
140
 
55
- # Check if ZIP archive exists and extract if needed
141
+ # Extract ZIP if needed using mixin
142
+ if not self.extract_zip_if_needed(base_dir, zip_path, self.app_name):
143
+ return render(request, 'frontend/404.html', status=404)
144
+
145
+ # Ensure directory exists
56
146
  if not base_dir.exists():
57
- zip_path = Path(django_cfg.__file__).parent / 'static' / 'frontend' / f'{self.app_name}.zip'
58
- if zip_path.exists():
59
- logger.info(f"Extracting {self.app_name}.zip to {base_dir}...")
60
- try:
61
- base_dir.parent.mkdir(parents=True, exist_ok=True)
62
- with zipfile.ZipFile(zip_path, 'r') as zip_ref:
63
- zip_ref.extractall(base_dir)
64
- logger.info(f"Successfully extracted {self.app_name}.zip")
65
- except Exception as e:
66
- logger.error(f"Failed to extract {self.app_name}.zip: {e}")
67
- return render(request, 'frontend/404.html', status=404)
68
- else:
69
- return render(request, 'frontend/404.html', status=404)
147
+ logger.error(f"[{self.app_name}] Directory doesn't exist after extraction attempt")
148
+ return render(request, 'frontend/404.html', status=404)
70
149
 
71
150
  original_path = path # Store for logging
72
151
 
@@ -2,6 +2,12 @@
2
2
  Views for Next.js admin integration.
3
3
 
4
4
  Serves Next.js static files with SPA routing support and JWT injection.
5
+
6
+ Features:
7
+ - Automatic extraction of ZIP archives with age-based refresh
8
+ - Auto-reextraction when directory is older than 10 minutes
9
+ - SPA routing with fallback strategies
10
+ - JWT token injection for authenticated users
5
11
  """
6
12
 
7
13
  import logging
@@ -13,24 +19,31 @@ from django.views.decorators.clickjacking import xframe_options_exempt
13
19
  from django.utils.decorators import method_decorator
14
20
  from django.contrib.auth.mixins import LoginRequiredMixin
15
21
  from django.shortcuts import render
22
+ from django_cfg.apps.frontend.views import ZipExtractionMixin
16
23
 
17
24
  logger = logging.getLogger(__name__)
18
25
 
19
26
 
20
27
  @method_decorator(xframe_options_exempt, name='dispatch')
21
- class NextJsAdminView(LoginRequiredMixin, View):
28
+ class NextJsAdminView(ZipExtractionMixin, LoginRequiredMixin, View):
22
29
  """
23
30
  Serve Next.js admin panel with JWT injection and SPA routing.
24
31
 
25
32
  Features:
26
33
  - Serves Next.js static build files
34
+ - Smart ZIP extraction: auto-refreshes when directory older than 10 minutes
27
35
  - Automatic JWT token injection for authenticated users
28
36
  - SPA routing support (path/to/route → path/to/route/index.html)
29
37
  - Development mode support (proxies to dev server conceptually)
30
38
 
39
+ ZIP Extraction Logic:
40
+ - If directory doesn't exist: extract from ZIP
41
+ - If directory older than 10 minutes: remove and re-extract
42
+ - If directory fresh (< 10 min): use existing files
43
+
31
44
  URL Examples:
32
- /cfg/admin/ → private.html (or index.html)
33
- /cfg/admin/private/centrifugo private/centrifugo/index.html
45
+ /cfg/admin/ → admin/index.html
46
+ /cfg/admin/crypto admin/crypto/index.html
34
47
  /cfg/admin/_next/static/... → _next/static/...
35
48
  """
36
49
 
@@ -38,7 +51,6 @@ class NextJsAdminView(LoginRequiredMixin, View):
38
51
  """Serve Next.js files with JWT injection and SPA routing."""
39
52
  from django_cfg.core.config import get_current_config
40
53
  import django_cfg
41
- import zipfile
42
54
 
43
55
  config = get_current_config()
44
56
  if not config or not config.nextjs_admin:
@@ -48,33 +60,24 @@ class NextJsAdminView(LoginRequiredMixin, View):
48
60
 
49
61
  # Use extracted directory from static/frontend/nextjs_admin/
50
62
  base_dir = Path(django_cfg.__file__).parent / 'static' / 'frontend' / 'nextjs_admin'
63
+ zip_path = Path(django_cfg.__file__).parent / 'static' / 'frontend' / 'nextjs_admin.zip'
64
+
65
+ # Fallback: Try solution project static directory
66
+ if not zip_path.exists():
67
+ from django.conf import settings
68
+ solution_zip = Path(settings.BASE_DIR) / 'static' / 'nextjs_admin.zip'
69
+ if solution_zip.exists():
70
+ zip_path = solution_zip
71
+ logger.info(f"[nextjs_admin] Using ZIP from solution project: {solution_zip}")
51
72
 
52
- # Check if ZIP archive exists and extract if needed
73
+ # Extract ZIP if needed using mixin
74
+ if not self.extract_zip_if_needed(base_dir, zip_path, 'nextjs_admin'):
75
+ return render(request, 'frontend/404.html', status=404)
76
+
77
+ # Ensure directory exists
53
78
  if not base_dir.exists():
54
- # Try django_cfg package location first
55
- zip_path = Path(django_cfg.__file__).parent / 'static' / 'frontend' / 'nextjs_admin.zip'
56
-
57
- # Fallback: Try solution project static directory
58
- if not zip_path.exists():
59
- from django.conf import settings
60
- solution_zip = Path(settings.BASE_DIR) / 'static' / 'nextjs_admin.zip'
61
- if solution_zip.exists():
62
- zip_path = solution_zip
63
- logger.info(f"Using ZIP from solution project: {solution_zip}")
64
-
65
- if zip_path.exists():
66
- logger.info(f"Extracting nextjs_admin.zip to {base_dir}...")
67
- try:
68
- base_dir.parent.mkdir(parents=True, exist_ok=True)
69
- with zipfile.ZipFile(zip_path, 'r') as zip_ref:
70
- zip_ref.extractall(base_dir)
71
- logger.info(f"Successfully extracted nextjs_admin.zip from {zip_path}")
72
- except Exception as e:
73
- logger.error(f"Failed to extract nextjs_admin.zip: {e}")
74
- return render(request, 'frontend/404.html', status=404)
75
- else:
76
- logger.error(f"nextjs_admin.zip not found in django_cfg or solution project")
77
- return render(request, 'frontend/404.html', status=404)
79
+ logger.error(f"[nextjs_admin] Directory doesn't exist after extraction attempt")
80
+ return render(request, 'frontend/404.html', status=404)
78
81
 
79
82
  static_dir = base_dir
80
83
 
django_cfg/pyproject.toml CHANGED
@@ -4,10 +4,10 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "django-cfg"
7
- version = "1.4.92"
8
- description = "Django AI framework with built-in agents, type-safe Pydantic v2 configuration, and 8 enterprise apps. Replace settings.py, validate at startup, 90% less code. Production-ready AI workflows for Django."
7
+ version = "1.4.94"
8
+ description = "Modern Django framework with type-safe Pydantic v2 configuration, Next.js admin integration, real-time WebSockets, and 8 enterprise apps. Replace settings.py with validated models, 90% less code. Production-ready with AI agents, auto-generated TypeScript clients, and zero-config features."
9
9
  readme = "README.md"
10
- keywords = [ "django", "configuration", "pydantic", "settings", "type-safety", "pydantic-settings", "django-environ", "startup-validation", "ide-autocomplete", "ai-agents", "enterprise-django", "django-settings", "type-safe-config",]
10
+ keywords = [ "django", "configuration", "pydantic", "settings", "type-safety", "pydantic-settings", "django-environ", "startup-validation", "ide-autocomplete", "nextjs-admin", "react-admin", "websocket", "centrifugo", "real-time", "typescript-generation", "ai-agents", "enterprise-django", "django-settings", "type-safe-config", "modern-django",]
11
11
  classifiers = [ "Development Status :: 4 - Beta", "Framework :: Django", "Framework :: Django :: 5.2", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: Dynamic Content", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: System :: Systems Administration", "Typing :: Typed",]
12
12
  requires-python = ">=3.12,<3.14"
13
13
  dependencies = [ "pydantic>=2.11.0,<3.0", "pydantic[email]>=2.11.0,<3.0", "PyYAML>=6.0,<7.0", "click>=8.2.0,<9.0", "questionary>=2.1.0,<3.0", "rich>=14.0.0,<15.0", "cloudflare>=4.3.0,<5.0", "loguru>=0.7.0,<1.0", "colorlog>=6.9.0,<7.0", "cachetools>=5.3.0,<7.0", "toml>=0.10.2,<0.11.0", "ngrok>=1.5.1; python_version>='3.12'", "psycopg[binary,pool]>=3.2.0,<4.0", "dj-database-url>=3.0.0,<4.0", "whitenoise>=6.8.0,<7.0", "django-cors-headers>=4.7.0,<5.0", "djangorestframework>=3.16.0,<4.0", "djangorestframework-simplejwt>=5.5.0,<6.0", "djangorestframework-simplejwt[token-blacklist]>=5.5.0,<6.0", "drf-nested-routers>=0.94.0,<1.0", "django-filter>=25.0,<26.0", "django-ratelimit>=4.1.0,<5.0.0", "drf-spectacular>=0.28.0,<1.0", "drf-spectacular-sidecar>=2025.8.0,<2026.0", "django-json-widget>=2.0.0,<3.0", "django-import-export>=4.3.0,<5.0", "django-extensions>=4.1.0,<5.0", "django-constance>=4.3.0,<5.0", "django-unfold>=0.64.0,<1.0", "django-redis>=6.0.0,<7.0", "redis>=6.4.0,<7.0", "hiredis>=2.0.0,<4.0", "dramatiq[redis]>=1.18.0,<2.0", "django-dramatiq>=0.14.0,<1.0", "pyTelegramBotAPI>=4.28.0,<5.0", "coolname>=2.2.0,<3.0", "django-admin-rangefilter>=0.13.0,<1.0", "python-json-logger>=3.3.0,<4.0", "requests>=2.32.0,<3.0", "tiktoken>=0.11.0,<1.0", "openai>=1.107.0,<2.0", "twilio>=9.8.0,<10.0", "sendgrid>=6.12.0,<7.0", "beautifulsoup4>=4.13.0,<5.0", "lxml>=6.0.0,<7.0", "pgvector>=0.4.0,<1.0", "tenacity>=9.1.2,<10.0.0", "mypy (>=1.18.2,<2.0.0)", "django-tailwind[reload] (>=4.2.0,<5.0.0)", "jinja2 (>=3.1.6,<4.0.0)", "django-axes[ipware] (>=8.0.0,<9.0.0)", "pydantic-settings (>=2.11.0,<3.0.0)",]
Binary file
@@ -79,7 +79,27 @@
79
79
  {% block content %}
80
80
  <!-- Main Container -->
81
81
  {% component "unfold/components/container.html" %}
82
- <div x-data="{ activeTab: 'builtin' }">
82
+ <div x-data="{
83
+ activeTab: 'builtin',
84
+ previousTab: 'builtin',
85
+ switchTab(tab) {
86
+ if (this.previousTab !== tab) {
87
+ // Reset iframe to initial URL when switching tabs
88
+ this.resetIframe(this.previousTab);
89
+ this.previousTab = tab;
90
+ }
91
+ this.activeTab = tab;
92
+ },
93
+ resetIframe(tab) {
94
+ // Reset the iframe that was just hidden
95
+ const iframeId = tab === 'builtin' ? 'nextjs-dashboard-iframe-builtin' : 'nextjs-dashboard-iframe-nextjs';
96
+ const iframe = document.getElementById(iframeId);
97
+ if (iframe) {
98
+ const originalSrc = iframe.getAttribute('data-original-src') || iframe.src;
99
+ iframe.src = originalSrc;
100
+ }
101
+ }
102
+ }">
83
103
  {% if is_frontend_dev_mode %}
84
104
  <!-- Development Mode Badge -->
85
105
  <div class="bg-yellow-100 dark:bg-yellow-900 border-l-4 border-yellow-500 text-yellow-700 dark:text-yellow-300 p-4 mb-4" role="alert">
@@ -106,7 +126,7 @@
106
126
  }
107
127
  </style>
108
128
  <nav class="-mb-px flex space-x-8 px-4" aria-label="Dashboard Tabs">
109
- <button @click="activeTab = 'builtin'"
129
+ <button @click="switchTab('builtin')"
110
130
  class="whitespace-nowrap py-4 px-2 border-b-2 font-medium text-sm flex items-center gap-2 transition-all duration-200"
111
131
  :class="activeTab === 'builtin'
112
132
  ? 'border-primary-600 text-primary-600 dark:border-primary-500 dark:text-primary-500'
@@ -115,7 +135,7 @@
115
135
  <span>Built-in Dashboard</span>
116
136
  </button>
117
137
 
118
- <button @click="activeTab = 'nextjs'"
138
+ <button @click="switchTab('nextjs')"
119
139
  class="whitespace-nowrap py-4 px-2 border-b-2 font-medium text-sm flex items-center gap-2 transition-all duration-200"
120
140
  :class="activeTab === 'nextjs'
121
141
  ? 'border-primary-600 text-primary-600 dark:border-primary-500 dark:text-primary-500'
@@ -140,6 +160,7 @@
140
160
  id="nextjs-dashboard-iframe-builtin"
141
161
  class="nextjs-dashboard-iframe"
142
162
  src="{% nextjs_admin_url %}"
163
+ data-original-src="{% nextjs_admin_url %}"
143
164
  title="Next.js Dashboard"
144
165
  sandbox="allow-same-origin allow-scripts allow-forms allow-popups allow-modals allow-storage-access-by-user-activation"
145
166
  scrolling="no"
@@ -160,6 +181,7 @@
160
181
  id="nextjs-dashboard-iframe-nextjs"
161
182
  class="nextjs-dashboard-iframe nextjs-external-iframe"
162
183
  src="{% nextjs_external_admin_url %}"
184
+ data-original-src="{% nextjs_external_admin_url %}"
163
185
  title="{% nextjs_external_admin_title %}"
164
186
  sandbox="allow-same-origin allow-scripts allow-forms allow-popups allow-modals allow-storage-access-by-user-activation"
165
187
  scrolling="no"
@@ -225,22 +247,62 @@
225
247
 
226
248
  // Debounce timer for resize events (prevents jittery iframe height changes)
227
249
  let resizeTimer = null;
250
+ let loadTimeout = null;
228
251
 
229
252
  // iframe load event
230
253
  iframe.addEventListener('load', function() {
254
+ // Clear the fallback timeout
255
+ if (loadTimeout) {
256
+ clearTimeout(loadTimeout);
257
+ loadTimeout = null;
258
+ }
259
+
231
260
  setTimeout(() => {
232
261
  sendDataToIframe();
233
262
  }, 100);
234
263
  });
235
264
 
236
- // Fallback: Show iframe after 5 seconds
237
- setTimeout(() => {
238
- if (!iframe.classList.contains('loaded')) {
265
+ // iframe error event - fallback to static files
266
+ iframe.addEventListener('error', function() {
267
+ console.warn('[Django-CFG] iframe failed to load, falling back to static files');
268
+ handleLoadFailure();
269
+ });
270
+
271
+ // Timeout fallback - if iframe doesn't load in 3 seconds
272
+ loadTimeout = setTimeout(() => {
273
+ if (!iframe.classList.contains('loaded') && isDevMode) {
274
+ console.warn('[Django-CFG] Dev server timeout, falling back to static files');
275
+ handleLoadFailure();
276
+ } else if (!iframe.classList.contains('loaded')) {
239
277
  console.log('[Django-CFG] Timeout - showing iframe anyway');
240
278
  if (loading) loading.classList.add('hidden');
241
279
  iframe.classList.add('loaded');
242
280
  }
243
- }, 5000);
281
+ }, 3000);
282
+
283
+ // Handle load failure - switch to static files
284
+ function handleLoadFailure() {
285
+ if (!isDevMode) return; // Already using static files
286
+
287
+ const originalSrc = iframe.getAttribute('data-original-src');
288
+ if (!originalSrc) return;
289
+
290
+ // Extract path from dev server URL
291
+ const devUrl = new URL(originalSrc);
292
+ const pathPart = devUrl.pathname.replace('/admin', '').replace(/^\//, '');
293
+
294
+ // Build static files URL
295
+ const staticUrl = `/cfg/admin/admin/${pathPart}`;
296
+
297
+ console.log('[Django-CFG] Switching to static files:', staticUrl);
298
+ iframe.src = staticUrl;
299
+
300
+ // Show iframe after switching
301
+ setTimeout(() => {
302
+ if (loading) loading.classList.add('hidden');
303
+ iframe.classList.add('loaded');
304
+ }, 500);
305
+ }
244
306
 
245
307
  // Send theme and auth data to iframe
246
308
  function sendDataToIframe() {
@@ -170,11 +170,10 @@ def nextjs_admin_url(path=''):
170
170
  Get the URL for Next.js Admin Panel (Built-in Dashboard - Tab 1).
171
171
 
172
172
  Auto-detects development mode with priority:
173
- 1. If port 3000 is available → use static files (Tab 2 gets dev server)
174
- 2. If only port 3001 is available http://localhost:3001/admin/{path}
175
- 3. Otherwise → /cfg/admin/admin/{path} (static files)
173
+ 1. If port 3001 is available → http://localhost:3001/admin/{path} (dev server)
174
+ 2. Otherwise → /cfg/admin/admin/{path} (static files)
176
175
 
177
- This ensures only ONE tab shows dev server at a time.
176
+ Note: Port 3000 is reserved for external Next.js admin (Tab 2).
178
177
 
179
178
  Usage in template:
180
179
  {% load django_cfg %}
@@ -188,20 +187,15 @@ def nextjs_admin_url(path=''):
188
187
  # Production mode: always use static files
189
188
  return f'/cfg/admin/admin/{path}' if path else '/cfg/admin/admin/'
190
189
 
191
- # Check which ports are available
192
- port_3000_available = _is_port_available('localhost', 3000)
190
+ # Check if port 3001 is available for Tab 1 (built-in admin)
193
191
  port_3001_available = _is_port_available('localhost', 3001)
194
192
 
195
- # Priority: if port 3000 is running, Tab 2 gets it, Tab 1 uses static
196
- if port_3000_available:
197
- # Solution project is running - use static files for Tab 1
198
- return f'/cfg/admin/admin/{path}' if path else '/cfg/admin/admin/'
199
- elif port_3001_available:
200
- # Dev project is running - use dev server for Tab 1
193
+ if port_3001_available:
194
+ # Dev server is running on 3001 - use it
201
195
  base_url = 'http://localhost:3001/admin'
202
196
  return f'{base_url}/{path}' if path else base_url
203
197
  else:
204
- # No dev server - use static files
198
+ # No dev server or dev server stopped - use static files
205
199
  return f'/cfg/admin/admin/{path}' if path else '/cfg/admin/admin/'
206
200
 
207
201
 
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-cfg
3
- Version: 1.4.92
4
- Summary: Django AI framework with built-in agents, type-safe Pydantic v2 configuration, and 8 enterprise apps. Replace settings.py, validate at startup, 90% less code. Production-ready AI workflows for Django.
3
+ Version: 1.4.94
4
+ Summary: Modern Django framework with type-safe Pydantic v2 configuration, Next.js admin integration, real-time WebSockets, and 8 enterprise apps. Replace settings.py with validated models, 90% less code. Production-ready with AI agents, auto-generated TypeScript clients, and zero-config features.
5
5
  Project-URL: Homepage, https://djangocfg.com
6
6
  Project-URL: Documentation, https://djangocfg.com
7
7
  Project-URL: Repository, https://github.com/markolofsen/django-cfg
@@ -11,7 +11,7 @@ Author-email: Django-CFG Team <info@djangocfg.com>
11
11
  Maintainer-email: Django-CFG Team <info@djangocfg.com>
12
12
  License: MIT
13
13
  License-File: LICENSE
14
- Keywords: ai-agents,configuration,django,django-environ,django-settings,enterprise-django,ide-autocomplete,pydantic,pydantic-settings,settings,startup-validation,type-safe-config,type-safety
14
+ Keywords: ai-agents,centrifugo,configuration,django,django-environ,django-settings,enterprise-django,ide-autocomplete,modern-django,nextjs-admin,pydantic,pydantic-settings,react-admin,real-time,settings,startup-validation,type-safe-config,type-safety,typescript-generation,websocket
15
15
  Classifier: Development Status :: 4 - Beta
16
16
  Classifier: Framework :: Django
17
17
  Classifier: Framework :: Django :: 5.2
@@ -148,7 +148,7 @@ Requires-Dist: pytest-xdist<4.0,>=3.8; extra == 'test'
148
148
  Requires-Dist: pytest<9.0,>=8.4; extra == 'test'
149
149
  Description-Content-Type: text/markdown
150
150
 
151
- # Django-CFG: Type-Safe Django Configuration Framework with AI-Ready Infrastructure
151
+ # Django-CFG: Type-Safe Django Configuration Framework
152
152
 
153
153
  [![Python 3.12+](https://img.shields.io/badge/python-3.12+-blue.svg?style=flat-square&logo=python)](https://www.python.org/downloads/)
154
154
  [![Django 5.2+](https://img.shields.io/badge/django-5.2+-green.svg?style=flat-square&logo=django)](https://www.djangoproject.com/)
@@ -165,119 +165,86 @@ Description-Content-Type: text/markdown
165
165
 
166
166
  <div align="center">
167
167
 
168
- ### 🚀 Pydantic Django Settings: Reduce Django Configuration Code by 90%
168
+ ### 🚀 The Modern Django Framework for Enterprise Applications
169
169
 
170
- **Type-safe Django configuration with Pydantic v2 models** • **Full IDE autocomplete** • **Startup validation** • **8 enterprise apps**
170
+ **Type-safe configuration** **Next.js Admin** • **AI Agents** • **Real-time WebSockets** • **8 Enterprise Apps**
171
171
 
172
- **[🤖 AI Project Generator](https://editor.djangocfg.com)** • **[🎯 Live Demo](http://demo.djangocfg.com)** • **[📚 Documentation](https://djangocfg.com/docs/getting-started/intro)**
172
+ **[🎯 Live Demo](http://demo.djangocfg.com)** • **[📚 Documentation](https://djangocfg.com/docs/getting-started/intro)** • **[🐙 GitHub](https://github.com/markolofsen/django-cfg)**
173
173
 
174
174
  </div>
175
175
 
176
- ## 🤖 AI Project Generator - Zero Setup Required
177
-
178
- **Describe your app in plain English, get production-ready Django project in 30 seconds:**
179
-
180
- > *"I need a SaaS app with user authentication, Stripe payments, and admin dashboard"*
181
-
182
- **AI generates:** ✅ Type-safe config • ✅ Database models • ✅ REST API + docs • ✅ Modern UI • ✅ Deployment ready
183
-
184
- ### **[→ Try AI Editor Now](https://editor.djangocfg.com)**
185
-
186
176
  ---
187
177
 
188
- ## 🎯 Type-Safe Django Configuration with Pydantic v2
178
+ ## 🎯 What is Django-CFG?
189
179
 
190
- **Django-CFG replaces error-prone `settings.py` with type-safe Pydantic models** - eliminate runtime configuration errors, get full IDE autocomplete, and validate settings at startup. The only Django configuration framework with built-in AI agents and enterprise apps.
180
+ **Django-CFG** is a next-generation Django framework that replaces traditional `settings.py` with **type-safe Pydantic v2 models**. It eliminates runtime configuration errors, provides complete IDE autocomplete, and includes **production-ready enterprise features** out of the box.
191
181
 
192
- ### Why Type-Safe Configuration Matters
182
+ ### Why Django-CFG?
193
183
 
194
- **Traditional Django settings.py problems:**
195
- - ❌ **Runtime errors** - typos caught in production, not at startup
196
- - ❌ **No IDE support** - zero autocomplete, manual docs lookup
197
- - ❌ **200+ lines** - unmaintainable configuration sprawl
198
- - ❌ **Manual validation** - environment variables unchecked until used
184
+ **Traditional Django problems:**
185
+ - ❌ **Runtime errors** - configuration bugs discovered in production
186
+ - ❌ **No IDE support** - zero autocomplete, manual documentation lookup
187
+ - ❌ **200+ lines** of unmaintainable settings.py
188
+ - ❌ **Weeks of setup** - for user auth, admin UI, payments, real-time features
199
189
 
200
- **Django-CFG Pydantic solution:**
201
- - ✅ **Compile-time validation** - catch errors before deployment
202
- - ✅ **Full IDE autocomplete** - IntelliSense for all settings
190
+ **Django-CFG solution:**
191
+ - ✅ **Startup validation** - catch all config errors before deployment
192
+ - ✅ **Full IDE autocomplete** - IntelliSense for every setting
203
193
  - ✅ **30 lines of code** - 90% boilerplate reduction
204
- - ✅ **Startup validation** - fail fast with clear error messages
194
+ - ✅ **30 seconds to production** - everything included and ready
205
195
 
206
- ### Django Configuration Comparison
207
-
208
- | Feature | settings.py | django-environ | pydantic-settings | **Django-CFG** |
209
- |---------|-------------|----------------|-------------------|----------------|
210
- | **Type Safety** | ❌ Runtime only | ⚠️ Basic casting | ✅ Pydantic | ✅ **Full Pydantic v2** |
211
- | **IDE Autocomplete** | ❌ None | ❌ None | ⚠️ Partial | ✅ **100%** |
212
- | **Startup Validation** | ❌ No | ⚠️ Partial | ✅ Yes | ✅ **Yes + Custom validators** |
213
- | **Django Integration** | ✅ Native | ⚠️ Partial | ❌ Manual | ✅ **Seamless** |
214
- | **Built-in Apps** | ❌ Build yourself | ❌ None | ❌ None | ✅ **8 enterprise apps** |
215
- | **AI-Ready** | ❌ Manual setup | ❌ None | ❌ None | ✅ **LLM + Vector DB** |
216
-
217
- **[📚 Full comparison guide →](https://djangocfg.com/docs/getting-started/django-cfg-vs-alternatives)**
196
+ **[📚 Read the full comparison →](https://djangocfg.com/docs/getting-started/django-cfg-vs-alternatives)**
218
197
 
219
198
  ---
220
199
 
221
- ## 🚀 Three Ways to Start
222
-
223
- ### Option 1: AI Editor (Fastest - 30 seconds) ⚡
224
-
225
- **Generate project with AI - no installation needed:**
200
+ ## 🚀 Quick Start
226
201
 
227
- 1. Go to **[editor.djangocfg.com](https://editor.djangocfg.com)**
228
- 2. Describe your app in plain English
229
- 3. Download ready-to-deploy project
230
-
231
- **[→ Generate with AI](https://editor.djangocfg.com)**
232
-
233
- ---
234
-
235
- ### Option 2: Traditional CLI
202
+ ### Installation
236
203
 
237
204
  ```bash
238
205
  pip install django-cfg
239
- django-cfg create-project "My SaaS App"
240
- cd my-saas-app && python manage.py runserver
206
+ django-cfg create-project "My App"
207
+ cd my-app && python manage.py runserver
241
208
  ```
242
209
 
243
210
  **What you get instantly:**
244
- - 🎨 Modern Admin UI → `http://127.0.0.1:8000/admin/`
245
- - 📚 API Docs`http://127.0.0.1:8000/api/docs/`
246
- - 🚀 Production-ready app
211
+ - 🎨 **Modern Admin UI** → `http://127.0.0.1:8000/admin/`
212
+ - **Next.js Dashboard** (optional) Modern React admin interface
213
+ - 📡 **Real-time WebSockets** → Live updates with Centrifugo
214
+ - 🚀 **Production-ready** → Type-safe config, security hardened
247
215
 
248
216
  <div align="center">
249
217
  <img src="https://raw.githubusercontent.com/markolofsen/django-cfg/refs/heads/main/static/startup.png" alt="Django-CFG Startup Screen" width="800">
250
- <p><em>Django-CFG startup screen showing type-safe configuration validation</em></p>
218
+ <p><em>Django-CFG startup with type-safe configuration validation</em></p>
251
219
  </div>
252
220
 
253
221
  **[📚 Installation Guide →](https://djangocfg.com/docs/getting-started/installation)**
254
222
 
255
223
  ---
256
224
 
257
- ### Option 3: Explore Live Demo First 🎯
225
+ ### Try Live Demo
258
226
 
259
- **See a real production Django-CFG app in action:**
227
+ **See Django-CFG in action:**
260
228
 
261
- ### **[→ http://demo.djangocfg.com](http://demo.djangocfg.com)**
229
+ **[→ http://demo.djangocfg.com](http://demo.djangocfg.com)**
262
230
 
263
231
  **Demo credentials:**
264
232
  - **Admin:** `demo@djangocfg.com` / `demo2024`
265
233
  - **User:** `user@djangocfg.com` / `user2024`
266
234
 
267
- **What you'll see:** Modern admin • Auto-generated API docs • AI agents • Support systemPayments
235
+ **Explore:** Modern admin • Next.js dashboard • AI agents • Real-time updatesSupport system
268
236
 
269
237
  ---
270
238
 
271
239
  ## 💡 Core Features
272
240
 
273
- ### 🔒 Type-Safe Django Settings with Pydantic v2 Models
274
-
275
- **Replace Django's settings.py with Pydantic v2 for complete type safety, IDE autocomplete, and startup validation.**
241
+ ### 🔒 Type-Safe Configuration with Pydantic v2
276
242
 
277
- #### Before: Django settings.py (Runtime Errors)
243
+ **Replace error-prone settings.py with validated Pydantic models.**
278
244
 
245
+ #### Before: Django settings.py
279
246
  ```python
280
- # settings.py - No type checking, runtime errors
247
+ # settings.py - Runtime errors, no validation
281
248
  import os
282
249
 
283
250
  DEBUG = os.getenv('DEBUG', 'False') == 'True' # ❌ String comparison bug
@@ -290,98 +257,164 @@ DATABASES = {
290
257
  'PORT': DATABASE_PORT, # ❌ Type mismatch in production
291
258
  }
292
259
  }
293
- # ... 200+ more lines of unvalidated configuration
260
+ # ... 200+ more lines
294
261
  ```
295
262
 
296
- #### After: Django-CFG (Type-Safe Pydantic Configuration)
297
-
263
+ #### After: Django-CFG
298
264
  ```python
299
- # config.py - Type-safe Pydantic Django settings
300
- from django_cfg import DjangoConfig
301
- from django_cfg.models import DatabaseConfig
265
+ # config.py - Type-safe, validated at startup
266
+ from django_cfg import DjangoConfig, DatabaseConfig
302
267
 
303
268
  class MyConfig(DjangoConfig):
304
- """Production-grade type-safe Django configuration"""
269
+ """Production-ready type-safe configuration"""
305
270
 
306
- project_name: str = "My SaaS App"
307
- debug: bool = False # ✅ Pydantic validates boolean conversion
271
+ project_name: str = "My App"
272
+ debug: bool = False # ✅ Pydantic validates boolean
308
273
 
309
- # Type-safe database configuration with startup validation
274
+ # Type-safe database with startup validation
310
275
  databases: dict[str, DatabaseConfig] = {
311
276
  "default": DatabaseConfig(
312
- name="${DB_NAME}", # ✅ Validated at startup
313
- port=5432, # ✅ Type-checked integer
277
+ name="${DB_NAME}", # ✅ Validated at startup
278
+ port=5432, # ✅ Type-checked integer
314
279
  )
315
280
  }
316
281
  ```
317
282
 
318
- **Django Configuration Benefits:**
319
- - ✅ **Pydantic v2 validation** - catch config errors before deployment
320
- - ✅ **Full IDE autocomplete** - IntelliSense for all Django settings
321
- - ✅ **90% less code** - reduce 200+ lines to 30 lines
322
- - ✅ **Type hints everywhere** - mypy and pyright compatible
283
+ **Benefits:**
284
+ - ✅ **Pydantic v2 validation** - catch errors before deployment
285
+ - ✅ **Full IDE autocomplete** - IntelliSense everywhere
286
+ - ✅ **90% less code** - 200+ lines 30 lines
287
+ - ✅ **Type hints** - mypy and pyright compatible
288
+
289
+ **[📚 Type-safe configuration guide →](https://djangocfg.com/docs/fundamentals/core/type-safety)**
290
+
291
+ ---
292
+
293
+ ### ⚛️ Next.js Admin Integration
294
+
295
+ **Build modern admin interfaces with React** - the only Django framework with built-in Next.js integration.
296
+
297
+ ```python
298
+ from django_cfg import DjangoConfig, NextJsAdminConfig
299
+
300
+ class MyConfig(DjangoConfig):
301
+ # One line for complete Next.js admin!
302
+ nextjs_admin: NextJsAdminConfig = NextJsAdminConfig(
303
+ project_path="../admin",
304
+ )
305
+ ```
306
+
307
+ **What you get:**
308
+ - 🌐 **Three-in-One Architecture** - Public site + User dashboard + Admin panel in ONE Next.js project
309
+ - ⚙️ **Dual Admin Strategy** - Django Unfold (90% quick CRUD) + Next.js (10% complex features)
310
+ - ✨ **Zero Configuration** - Auto JWT auth, theme sync, TypeScript generation
311
+ - 📦 **60% Smaller** - ZIP deployment (~7MB vs ~20MB)
312
+ - ⚡ **Auto-Detection** - Dev mode automatically detected on ports 3000/3001
313
+
314
+ **No migration needed** - start with built-in admin, add Next.js when you need complex features!
323
315
 
324
- **[📚 Type-safe configuration guide →](https://djangocfg.com/docs/getting-started/configuration)**
316
+ **[📚 Next.js Admin Documentation →](https://djangocfg.com/docs/features/integrations/nextjs-admin)**
325
317
 
326
318
  ---
327
319
 
328
- ### 🤖 AI Django Framework - Production-Ready AI Agents
320
+ ### 📡 Real-Time WebSockets with Centrifugo
329
321
 
330
- **Django AI integration made simple** - type-safe AI agents, LLM workflow automation, and vector database built into Django.
322
+ **Production-ready WebSocket integration** - live updates, notifications, and real-time collaboration.
323
+
324
+ ```python
325
+ from django_cfg import DjangoConfig, CentrifugoConfig
326
+
327
+ class MyConfig(DjangoConfig):
328
+ # Enable real-time features
329
+ centrifugo: CentrifugoConfig = CentrifugoConfig(
330
+ enabled=True,
331
+ api_url="http://localhost:8001/api",
332
+ )
333
+ ```
334
+
335
+ **Built-in features:**
336
+ - ⚡ **Live Updates** - Real-time data synchronization
337
+ - 🔔 **Notifications** - Push notifications to connected clients
338
+ - 👥 **Presence** - Track online users
339
+ - 💬 **Chat** - Real-time messaging out of the box
340
+ - 🔒 **JWT Auth** - Secure WebSocket connections
341
+
342
+ **[📚 Centrifugo Integration Guide →](https://djangocfg.com/docs/features/integrations/centrifugo)**
343
+
344
+ ---
345
+
346
+ ### 🤖 AI-Ready Infrastructure
347
+
348
+ **Built-in AI agent framework** - LLM workflow automation with Django ORM integration.
331
349
 
332
350
  ```python
333
351
  from django_cfg import DjangoConfig
334
352
 
335
353
  class MyConfig(DjangoConfig):
336
- # AI-powered Django development - zero setup
354
+ # AI features (optional)
337
355
  openai_api_key: str = "${OPENAI_API_KEY}"
338
356
  anthropic_api_key: str = "${ANTHROPIC_API_KEY}"
339
357
 
340
- # Enable AI Django agents (optional)
341
- enable_agents: bool = True # AI workflow automation
342
- enable_knowbase: bool = True # Vector database + RAG
358
+ enable_agents: bool = True # AI workflow automation
359
+ enable_knowbase: bool = True # Vector DB + RAG
343
360
  ```
344
361
 
345
- **Django AI Features:**
346
- - 🤖 **AI Agents Framework** - Type-safe Django LLM integration
347
- - 📚 **Vector Database** - ChromaDB semantic search for Django
348
- - 🔍 **RAG Integration** - Retrieval-augmented generation built-in
349
- - 🎯 **Pydantic AI** - Type-safe AI input/output validation
350
- - 🌐 **Multi-LLM** - OpenAI, Anthropic, Claude API support
362
+ **Features:**
363
+ - 🤖 **AI Agents Framework** - Type-safe LLM integration
364
+ - 📚 **Vector Database** - ChromaDB for semantic search
365
+ - 🔍 **RAG** - Retrieval-augmented generation
366
+ - 🎯 **Pydantic AI** - Validated AI input/output
367
+ - 🌐 **Multi-LLM** - OpenAI, Anthropic, Claude support
351
368
 
352
- **[📚 Django AI agents guide →](https://djangocfg.com/docs/ai-agents/introduction)**
369
+ **[📚 AI Agents Guide →](https://djangocfg.com/docs/ai-agents/introduction)**
353
370
 
354
371
  ---
355
372
 
356
- ### 📦 8 Production-Ready Enterprise Apps
373
+ ### 📦 8 Enterprise Apps Included
357
374
 
358
- **Ship features in days, not months** - everything you need is included:
375
+ **Ship features in days, not months** - production-ready apps out of the box:
359
376
 
360
- - **👤 Accounts** - User management + OTP + SMS auth
361
- - **🎫 Support** - Ticketing system + SLA tracking
362
- - **📧 Newsletter** - Email campaigns + analytics
363
- - **📊 Leads** - CRM + sales pipeline
364
- - **🤖 AI Agents** - Optional workflow automation
365
- - **📚 KnowBase** - Optional AI knowledge base + RAG
366
- - **💳 Payments** - Multi-provider crypto/fiat payments
367
- - **🔧 Maintenance** - Multi-site Cloudflare management
377
+ | App | Description | Time Saved |
378
+ |-----|-------------|------------|
379
+ | 👤 **Accounts** | User management + OTP + SMS auth | 3-4 weeks |
380
+ | 🎫 **Support** | Ticketing system + SLA tracking | 2-3 weeks |
381
+ | 📧 **Newsletter** | Email campaigns + analytics | 2-3 weeks |
382
+ | 📊 **Leads** | CRM + sales pipeline | 2-3 weeks |
383
+ | 🤖 **AI Agents** | Workflow automation | 3-4 weeks |
384
+ | 📚 **KnowBase** | AI knowledge base + RAG | 2-3 weeks |
385
+ | 💳 **Payments** | Multi-provider payments | 2-3 weeks |
386
+ | 🔧 **Maintenance** | Multi-site management | 1-2 weeks |
368
387
 
369
- **Total time saved: 18 months of development**
388
+ **Total time saved: 18+ months of development**
370
389
 
371
- **[📚 Explore all apps →](https://djangocfg.com/docs/features/built-in-apps)**
390
+ ```python
391
+ class MyConfig(DjangoConfig):
392
+ # Enable apps as needed (one line each!)
393
+ enable_accounts: bool = True
394
+ enable_support: bool = True
395
+ enable_newsletter: bool = True
396
+ enable_leads: bool = True
397
+ enable_agents: bool = True
398
+ enable_knowbase: bool = True
399
+ enable_payments: bool = True
400
+ enable_maintenance: bool = True
401
+ ```
402
+
403
+ **[📚 Built-in Apps Overview →](https://djangocfg.com/docs/features/built-in-apps/overview)**
372
404
 
373
405
  ---
374
406
 
375
407
  ### 🎨 Modern API UI with Tailwind 4
376
408
 
377
- **Beautiful browsable API** - 88% smaller bundle, 66% faster than old DRF UI.
409
+ **Beautiful browsable API** - 88% smaller bundle, modern design.
378
410
 
379
411
  - ✅ Glass morphism design
380
412
  - ✅ Light/Dark/Auto themes
381
413
  - ✅ Command palette (⌘K)
382
- - ✅ 88% smaller bundle (278KB → 33KB)
414
+ - ✅ 88% smaller (278KB → 33KB)
415
+ - ✅ Auto-generated TypeScript clients
383
416
 
384
- **[📚 See API Theme →](https://djangocfg.com/docs/features/api-generation)**
417
+ **[📚 API Generation Guide →](https://djangocfg.com/docs/features/api-generation/overview)**
385
418
 
386
419
  ---
387
420
 
@@ -390,43 +423,58 @@ class MyConfig(DjangoConfig):
390
423
  **Zero-config database routing** with automatic sharding:
391
424
 
392
425
  ```python
393
- databases: dict[str, DatabaseConfig] = {
394
- "analytics": DatabaseConfig(
395
- name="${ANALYTICS_DB}",
396
- routing_apps=["analytics", "reports"], # Auto-route!
397
- ),
398
- }
426
+ from django_cfg import DjangoConfig, DatabaseConfig
427
+
428
+ class MyConfig(DjangoConfig):
429
+ databases: dict[str, DatabaseConfig] = {
430
+ "default": DatabaseConfig(
431
+ name="${DB_NAME}",
432
+ ),
433
+ "analytics": DatabaseConfig(
434
+ name="${ANALYTICS_DB}",
435
+ routing_apps=["analytics", "reports"], # Auto-route!
436
+ ),
437
+ }
399
438
  ```
400
439
 
401
440
  ✅ Auto-routes read/write • ✅ Cross-DB transactions • ✅ Connection pooling
402
441
 
403
- **[📚 Multi-DB Guide →](https://djangocfg.com/docs/fundamentals/database)**
442
+ **[📚 Multi-Database Guide →](https://djangocfg.com/docs/fundamentals/database/multi-database)**
404
443
 
405
444
  ---
406
445
 
407
446
  ## ⚙️ Complete Configuration Example
408
447
 
409
- **All available apps and integrations in one DjangoConfig:**
448
+ **All features in one DjangoConfig:**
410
449
 
411
450
  ```python
412
- from django_cfg import DjangoConfig
413
- from django_cfg.models import DatabaseConfig, CacheConfig
451
+ from django_cfg import DjangoConfig, DatabaseConfig, CacheConfig, NextJsAdminConfig
414
452
 
415
453
  class ProductionConfig(DjangoConfig):
416
- # Project settings
454
+ # Project
417
455
  project_name: str = "My Enterprise App"
418
456
  secret_key: str = "${SECRET_KEY}"
419
457
  debug: bool = False
420
458
 
421
- # 8 Built-in Enterprise Apps (enable as needed)
422
- enable_accounts: bool = True # 👤 User management + OTP + SMS
423
- enable_support: bool = True # 🎫 Ticketing + SLA tracking
424
- enable_newsletter: bool = True # 📧 Email campaigns
425
- enable_leads: bool = True # 📊 CRM + sales pipeline
426
- enable_agents: bool = True # 🤖 AI workflow automation
427
- enable_knowbase: bool = True # 📚 AI knowledge base + RAG
428
- enable_payments: bool = True # 💳 Crypto/fiat payments
429
- enable_maintenance: bool = True # 🔧 Cloudflare management
459
+ # Next.js Admin (optional)
460
+ nextjs_admin: NextJsAdminConfig = NextJsAdminConfig(
461
+ project_path="../admin",
462
+ )
463
+
464
+ # Real-time WebSockets (optional)
465
+ centrifugo: CentrifugoConfig = CentrifugoConfig(
466
+ enabled=True,
467
+ )
468
+
469
+ # 8 Enterprise Apps (enable as needed)
470
+ enable_accounts: bool = True # User management
471
+ enable_support: bool = True # Ticketing
472
+ enable_newsletter: bool = True # Email campaigns
473
+ enable_leads: bool = True # CRM
474
+ enable_agents: bool = True # AI automation
475
+ enable_knowbase: bool = True # Vector DB
476
+ enable_payments: bool = True # Payments
477
+ enable_maintenance: bool = True # Site management
430
478
 
431
479
  # Infrastructure
432
480
  databases: dict[str, DatabaseConfig] = {
@@ -440,75 +488,84 @@ class ProductionConfig(DjangoConfig):
440
488
  openai_api_key: str = "${OPENAI_API_KEY}"
441
489
  anthropic_api_key: str = "${ANTHROPIC_API_KEY}"
442
490
 
443
- # Third-party Integrations
444
- twilio_account_sid: str = "${TWILIO_ACCOUNT_SID}" # SMS
445
- stripe_api_key: str = "${STRIPE_API_KEY}" # Payments
446
- cloudflare_api_token: str = "${CF_API_TOKEN}" # CDN/DNS
491
+ # Integrations
492
+ twilio_account_sid: str = "${TWILIO_ACCOUNT_SID}"
493
+ stripe_api_key: str = "${STRIPE_API_KEY}"
494
+ cloudflare_api_token: str = "${CF_API_TOKEN}"
447
495
  ```
448
496
 
449
- **[📚 Full configuration reference →](https://djangocfg.com/docs/getting-started/configuration)**
497
+ **[📚 Configuration Reference →](https://djangocfg.com/docs/getting-started/configuration)**
450
498
 
451
499
  ---
452
500
 
453
- ## 📊 Django Configuration Framework Comparison
501
+ ## 📊 Comparison with Alternatives
454
502
 
455
- **Django-CFG vs Traditional Django, DRF, FastAPI, and django-environ:**
503
+ ### Django-CFG vs Traditional Solutions
456
504
 
457
- | Feature | Django settings.py | django-environ | DRF | FastAPI | **Django-CFG** |
458
- |---------|-------------------|----------------|-----|---------|----------------|
459
- | **Type-Safe Config** | ❌ Runtime | ⚠️ Basic | ❌ Manual | ✅ Pydantic | ✅ **Full Pydantic v2** |
460
- | **IDE Autocomplete** | ❌ None | ❌ None | ❌ Manual | ⚠️ Partial | ✅ **100% IntelliSense** |
461
- | **Startup Validation** | ❌ No | ⚠️ Partial | ❌ No | ✅ Yes | ✅ **Pydantic + Custom** |
462
- | **Django Integration** | Native | Native | ✅ Native | Manual | ✅ **Seamless** |
463
- | **Admin UI** | 🟡 Basic | 🟡 Basic | 🟡 Basic | ❌ None | ✅ **Modern Unfold** |
464
- | **API Docs** | ❌ Manual | ❌ Manual | 🟡 Basic | ✅ Auto | ✅ **OpenAPI + Swagger** |
465
- | **AI Agents Built-in** | ❌ Manual | ❌ None | ❌ Manual | ❌ Manual | ✅ **LLM Framework** |
466
- | **Setup Time** | 🟡 Weeks | 🟡 Hours | 🟡 Weeks | 🟡 Days | ✅ **30 seconds** |
467
- | **Enterprise Apps** | Build all | None | Build all | ❌ Build all | ✅ **8 included** |
468
- | **Configuration Lines** | ⚠️ 200+ | ⚠️ 150+ | ⚠️ 200+ | ⚠️ 100+ | ✅ **30 lines** |
505
+ | Feature | settings.py | django-environ | pydantic-settings | **Django-CFG** |
506
+ |---------|-------------|----------------|-------------------|----------------|
507
+ | **Type Safety** | ❌ Runtime | ⚠️ Basic | ✅ Pydantic | ✅ **Full Pydantic v2** |
508
+ | **IDE Autocomplete** | ❌ None | ❌ None | ⚠️ Partial | ✅ **100%** |
509
+ | **Startup Validation** | ❌ No | ⚠️ Partial | ✅ Yes | ✅ **Yes + Custom** |
510
+ | **Next.js Admin** | Manual | None | ❌ None | ✅ **Built-in** |
511
+ | **WebSocket (Centrifugo)** | Manual | None | ❌ None | ✅ **Built-in** |
512
+ | **Enterprise Apps** | ❌ Build all | ❌ None | None | ✅ **8 included** |
513
+ | **AI Framework** | ❌ Manual | ❌ None | ❌ None | ✅ **Built-in** |
514
+ | **Setup Time** | 🟡 Weeks | 🟡 Hours | 🟡 Days | ✅ **30 seconds** |
515
+ | **Config Lines** | ⚠️ 200+ | ⚠️ 150+ | ⚠️ 100+ | ✅ **30 lines** |
469
516
 
470
517
  **Legend:** ✅ Excellent | 🟡 Requires Work | ⚠️ Partial | ❌ Not Available
471
518
 
472
- **[📚 Django-CFG vs django-environ detailed comparison →](https://djangocfg.com/docs/getting-started/django-cfg-vs-alternatives)**
519
+ **[📚 Detailed Comparison Guide →](https://djangocfg.com/docs/getting-started/django-cfg-vs-alternatives)**
473
520
 
474
521
  ---
475
522
 
476
523
  ## 📚 Documentation
477
524
 
478
525
  ### 🚀 Getting Started
479
- - **[Installation](https://djangocfg.com/docs/getting-started/installation)** - Quick setup guide
526
+ - **[Installation](https://djangocfg.com/docs/getting-started/installation)** - Quick setup
480
527
  - **[First Project](https://djangocfg.com/docs/getting-started/first-project)** - Create your first app
481
- - **[Configuration](https://djangocfg.com/docs/getting-started/configuration)** - Type-safe config guide
528
+ - **[Configuration](https://djangocfg.com/docs/getting-started/configuration)** - Type-safe config
482
529
  - **[Why Django-CFG?](https://djangocfg.com/docs/getting-started/why-django-cfg)** - Full comparison
483
530
 
531
+ ### ⚛️ Next.js Integration
532
+ - **[Overview](https://djangocfg.com/docs/features/integrations/nextjs-admin)** - Three-in-One architecture
533
+ - **[Core Concepts](https://djangocfg.com/docs/features/integrations/nextjs-admin/concepts)** - Philosophy & design
534
+ - **[Quick Start](https://djangocfg.com/docs/features/integrations/nextjs-admin/quick-start)** - 5-minute setup
535
+ - **[Configuration](https://djangocfg.com/docs/features/integrations/nextjs-admin/configuration)** - All options
536
+
537
+ ### 📡 Real-Time Features
538
+ - **[Centrifugo Integration](https://djangocfg.com/docs/features/integrations/centrifugo)** - WebSocket setup
539
+ - **[Live Updates](https://djangocfg.com/docs/features/integrations/centrifugo/live-updates)** - Real-time data
540
+
484
541
  ### 🏗️ Core Features
485
- - **[Built-in Apps](https://djangocfg.com/docs/features/built-in-apps)** - 8 enterprise apps
486
- - **[API Generation](https://djangocfg.com/docs/features/api-generation)** - Auto OpenAPI docs
487
- - **[Database](https://djangocfg.com/docs/fundamentals/database)** - Multi-DB routing
488
- - **[Integrations](https://djangocfg.com/docs/features/integrations)** - Third-party services
542
+ - **[Built-in Apps](https://djangocfg.com/docs/features/built-in-apps/overview)** - 8 enterprise apps
543
+ - **[API Generation](https://djangocfg.com/docs/features/api-generation/overview)** - Auto TypeScript clients
544
+ - **[Database](https://djangocfg.com/docs/fundamentals/database/multi-database)** - Multi-DB routing
545
+ - **[Type Safety](https://djangocfg.com/docs/fundamentals/core/type-safety)** - Pydantic validation
489
546
 
490
- ### 🤖 AI Integration (Optional)
547
+ ### 🤖 AI Features (Optional)
491
548
  - **[AI Agents](https://djangocfg.com/docs/ai-agents/introduction)** - Workflow automation
492
549
  - **[Creating Agents](https://djangocfg.com/docs/ai-agents/creating-agents)** - Build custom agents
493
- - **[Django Integration](https://djangocfg.com/docs/ai-agents/django-integration)** - Connect to your app
550
+ - **[Django Integration](https://djangocfg.com/docs/ai-agents/django-integration)** - ORM integration
494
551
 
495
552
  ### 🚀 Deployment
496
- - **[Production Config](https://djangocfg.com/docs/deployment)** - Production best practices
497
- - **[CLI Commands](https://djangocfg.com/docs/cli)** - 50+ management commands
553
+ - **[Production Config](https://djangocfg.com/docs/deployment)** - Best practices
554
+ - **[CLI Commands](https://djangocfg.com/docs/cli)** - 50+ commands
498
555
 
499
556
  ---
500
557
 
501
558
  ## 🤝 Community & Support
502
559
 
503
560
  ### Resources
504
- - 🌐 **[djangocfg.com](https://djangocfg.com/)** - Official website & documentation
561
+ - 🌐 **[djangocfg.com](https://djangocfg.com/)** - Official website & docs
505
562
  - 🐙 **[GitHub](https://github.com/markolofsen/django-cfg)** - Source code & issues
506
563
  - 💬 **[Discussions](https://github.com/markolofsen/django-cfg/discussions)** - Community support
507
564
 
508
565
  ### Links
509
- - **[🚀 AI Project Generator](https://editor.djangocfg.com)** - Generate projects with AI
510
566
  - **[🎯 Live Demo](http://demo.djangocfg.com)** - See it in action
511
567
  - **[📦 PyPI](https://pypi.org/project/django-cfg/)** - Package repository
568
+ - **[📚 Documentation](https://djangocfg.com/docs)** - Complete guides
512
569
 
513
570
  ---
514
571
 
@@ -524,12 +581,12 @@ class ProductionConfig(DjangoConfig):
524
581
 
525
582
  <div align="center">
526
583
 
527
- **Django AI Framework** • **Type-Safe Configuration** • **Pydantic Settings** • **Enterprise Apps**
584
+ **Modern Django Framework** • **Type-Safe Configuration** • **Next.js Admin** • **Real-Time WebSockets** • **AI-Ready**
528
585
 
529
- Django-CFG is the AI-first Django framework for production-ready AI agents, type-safe Pydantic v2 configuration, and enterprise development. Replace settings.py with validated models, build AI workflows with Django ORM integration, and ship faster with 8 built-in apps. Perfect for Django LLM integration, AI-powered Django development, scalable Django architecture, and reducing Django boilerplate.
586
+ Django-CFG is the modern Django framework for enterprise applications. Built with Pydantic v2 for type-safe configuration, includes Next.js admin integration, Centrifugo WebSocket support, AI agent framework, and 8 production-ready apps. Perfect for building scalable Django applications with reduced boilerplate and enterprise features out of the box.
530
587
 
531
588
  ---
532
589
 
533
- **Get Started:** **[Documentation](https://djangocfg.com/docs/getting-started/intro)** • **[AI Project Generator](https://editor.djangocfg.com)** • **[Live Demo](http://demo.djangocfg.com)**
590
+ **Get Started:** **[Documentation](https://djangocfg.com/docs/getting-started/intro)** • **[Live Demo](http://demo.djangocfg.com)** • **[GitHub](https://github.com/markolofsen/django-cfg)**
534
591
 
535
592
  </div>
@@ -1,5 +1,5 @@
1
1
  django_cfg/README.md,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- django_cfg/__init__.py,sha256=pz7YbfETPVh0YKhFH8_iJUk4fnnsYc3GSgN4nzqt-cE,1620
2
+ django_cfg/__init__.py,sha256=-eM13Z1Uie8EJUy2384SNHfso1SqzwpkDsmrQgWQN3w,1620
3
3
  django_cfg/apps.py,sha256=72m3uuvyqGiLx6gOfE-BD3P61jddCCERuBOYpxTX518,1605
4
4
  django_cfg/config.py,sha256=y4Z3rnYsHBE0TehpwAIPaxr---mkvyKrZGGsNwYso74,1398
5
5
  django_cfg/apps/__init__.py,sha256=JtDmEYt1OcleWM2ZaeX0LKDnRQzPOavfaXBWG4ECB5Q,26
@@ -228,7 +228,7 @@ django_cfg/apps/frontend/apps.py,sha256=9eEK0Tq2nOsol7xSK5aobdwTDJTJrWx6Iy1I1DQb
228
228
  django_cfg/apps/frontend/setup.py,sha256=TxKQwQw4xTF6VSyhrQBzbUsdsVQR9JHdjc36LZKeQh4,2444
229
229
  django_cfg/apps/frontend/test_routing.py,sha256=fshJOR9ln7m3gXY9EI1_ix_6E5xua6DR264b16RIF-w,4832
230
230
  django_cfg/apps/frontend/urls.py,sha256=Vz22_2i2w1J0KQYDCxHnTF5rUf32kUUSBDJZrP07XgY,284
231
- django_cfg/apps/frontend/views.py,sha256=dcdzrVZGIZ_IdlJJwQ4bpGw4x8V3GYGmv1Dc_xxXZIQ,10406
231
+ django_cfg/apps/frontend/views.py,sha256=JkObFoAJATT2gy6TnyFi0LrjQm7HGWaRy3vr2zdTs4E,13586
232
232
  django_cfg/apps/frontend/templates/frontend/404.html,sha256=LCFig_dcgDDmYKhgOLu8R2KDs_aQS6Es6rAxLTAEXWs,2175
233
233
  django_cfg/apps/knowbase/README.md,sha256=HXt_J6WCN-LsMhA7p9mdvih07_vp_r_hkPdmqHhNEeo,3965
234
234
  django_cfg/apps/knowbase/__init__.py,sha256=cfGnxDQwjajPhUoleKkgvdabJcB0LdXEglnsBojKkPo,1045
@@ -1021,7 +1021,7 @@ django_cfg/modules/django_unfold/models/navigation.py,sha256=PPEeqA2HBaA1-VjADiX
1021
1021
  django_cfg/modules/nextjs_admin/__init__.py,sha256=lfrZYyNRExH3Z5De8G4hQBIZoFlW5Ejze3couNrztbY,312
1022
1022
  django_cfg/modules/nextjs_admin/apps.py,sha256=HxVUMmWTKdYpwJ00iIfWVFsBzsawsOVhEPZqjk_izjI,347
1023
1023
  django_cfg/modules/nextjs_admin/urls.py,sha256=7n0yStm0WNchw14Rtu_mgsIA3WKQsYP9WZt3-YOUWjU,603
1024
- django_cfg/modules/nextjs_admin/views.py,sha256=SxpFQeRas0FsolZ4QNCqDEAVhncGxnDP4HtamuUsTu0,9655
1024
+ django_cfg/modules/nextjs_admin/views.py,sha256=lOcK-XLucWn-W4LORgk0XBEJkolYvSvsnp4Pq77oBBY,9657
1025
1025
  django_cfg/modules/nextjs_admin/models/__init__.py,sha256=WGw9KXcYd1O9AoA_bpMoz2gLZUlRzjGmUBjjbObcUi0,100
1026
1026
  django_cfg/modules/nextjs_admin/models/config.py,sha256=0ADqLuiywSCQfx_z9dkwjFCca3lr3F2uQffIjTr_QXw,5864
1027
1027
  django_cfg/modules/nextjs_admin/templatetags/__init__.py,sha256=ChVBnJggCIY8rMhfyJFoA8k0qKo-8FtJknrk54Vx4wM,51
@@ -1051,7 +1051,7 @@ django_cfg/static/admin/js/alpine/dashboard-tabs.js,sha256=ob8Q_I9lFLDv_hFERXgTy
1051
1051
  django_cfg/static/admin/js/alpine/system-metrics.js,sha256=m-Fg55K_vpHXToD46PXL9twl4OBF_V9MONvbSWbQqDw,440
1052
1052
  django_cfg/static/admin/js/alpine/toggle-section.js,sha256=T141NFmy0fRJyGGuuaCJRjJXwPam-xxtQNW1hi8BJbc,672
1053
1053
  django_cfg/static/frontend/admin.zip,sha256=n2G8ajruLqojcjqvw2pMEPjgpSTTwcmJxkeIQxJVw9U,7626768
1054
- django_cfg/static/frontend/nextjs_admin.zip,sha256=KZMpJgmsL-Gx-la-zLCpV0W2pZ0X94IrPqNNK8fmGB0,7509389
1054
+ django_cfg/static/frontend/nextjs_admin.zip,sha256=BsnMjrr9vx1Lh1zadBEBFGeP-Cn_eLjhWfkWk1m0fEw,7548272
1055
1055
  django_cfg/static/js/api-loader.mjs,sha256=boGqqRGnFR-Mzo_RQOjhAzNvsb7QxZddSwMKROzkk9Q,5163
1056
1056
  django_cfg/static/js/api/base.mjs,sha256=KUxZHHdELAV8mNnACpwJRvaQhdJxp-n5LFEQ4oUZxBo,4707
1057
1057
  django_cfg/static/js/api/index.mjs,sha256=_-Q04jjHcgwi4CGfiaLyiOR6NW7Yu1HBhJWp2J1cjpc,2538
@@ -1073,11 +1073,11 @@ django_cfg/static/js/api/support/index.mjs,sha256=oPA3iGkUWYyKQuJlI5-tSxD3AOhwlA
1073
1073
  django_cfg/static/js/api/tasks/client.mjs,sha256=tIy8K-finXzTUL9kOo_L4Q1kchDaHyuzjwS4VymiWPM,3579
1074
1074
  django_cfg/static/js/api/tasks/index.mjs,sha256=yCY1GzdD-RtFZ3pAfk1l0msgO1epyo0lsGCjH0g1Afc,294
1075
1075
  django_cfg/templates/__init__.py,sha256=IzLjt-a7VIJ0OutmAE1_-w0_LpL2u0MgGpnIabjZuW8,19
1076
- django_cfg/templates/admin/index.html,sha256=6-f3b2IfMkK_Qog5jHzeotqn3GAeLE7JpJIVoDA67L8,15302
1076
+ django_cfg/templates/admin/index.html,sha256=RidRvZwc6LFzRi8l6vHBgyM_CD0yvhPWvr40uVKCClY,18138
1077
1077
  django_cfg/templates/emails/base_email.html,sha256=TWcvYa2IHShlF_E8jf1bWZStRO0v8G4L_GexPxvz6XQ,8836
1078
1078
  django_cfg/templates/unfold/layouts/skeleton.html,sha256=2ArkcNZ34mFs30cOAsTQ1EZiDXcB0aVxkO71lJq9SLE,718
1079
1079
  django_cfg/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1080
- django_cfg/templatetags/django_cfg.py,sha256=7lGod6_K8AonRAUIZksluN6SWoxqQjke67D-lllMpY8,9670
1080
+ django_cfg/templatetags/django_cfg.py,sha256=0m7YadW6ifWuUEA9qe9IZ6zY4wt4F4ke0RXo3ngA5p8,9334
1081
1081
  django_cfg/utils/__init__.py,sha256=64wwXJuXytvwt8Ze_erSR2HmV07nGWJ6DV5wloRBvYE,435
1082
1082
  django_cfg/utils/path_resolution.py,sha256=2n0I04lQkSssFaELu3A93YyMAl1K10KPdpxMt5k4Iy0,13341
1083
1083
  django_cfg/utils/smart_defaults.py,sha256=ZUj6K_Deq-fp5O0Dy_Emt257UWFn0f9bkgFv9YCR58U,9239
@@ -1085,9 +1085,9 @@ django_cfg/utils/version_check.py,sha256=WO51J2m2e-wVqWCRwbultEwu3q1lQasV67Mw2aa
1085
1085
  django_cfg/CHANGELOG.md,sha256=jtT3EprqEJkqSUh7IraP73vQ8PmKUMdRtznQsEnqDZk,2052
1086
1086
  django_cfg/CONTRIBUTING.md,sha256=DU2kyQ6PU0Z24ob7O_OqKWEYHcZmJDgzw-lQCmu6uBg,3041
1087
1087
  django_cfg/LICENSE,sha256=xHuytiUkSZCRG3N11nk1X6q1_EGQtv6aL5O9cqNRhKE,1071
1088
- django_cfg/pyproject.toml,sha256=HlcU42lQgCt8Qn4XJAjcIuIaU2X1wsjmzqMV-9G0fKI,8370
1089
- django_cfg-1.4.92.dist-info/METADATA,sha256=CiXTzDGbsjBbZ7aDnUUNERfR1FR8Kz_VlV50BAOjUNM,22624
1090
- django_cfg-1.4.92.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
1091
- django_cfg-1.4.92.dist-info/entry_points.txt,sha256=Ucmde4Z2wEzgb4AggxxZ0zaYDb9HpyE5blM3uJ0_VNg,56
1092
- django_cfg-1.4.92.dist-info/licenses/LICENSE,sha256=xHuytiUkSZCRG3N11nk1X6q1_EGQtv6aL5O9cqNRhKE,1071
1093
- django_cfg-1.4.92.dist-info/RECORD,,
1088
+ django_cfg/pyproject.toml,sha256=J8hwDLhnybgAGUsvUNdXFimKoEuj7Lc9SH1n5f_Q0gY,8572
1089
+ django_cfg-1.4.94.dist-info/METADATA,sha256=Xhg1mauCgGfgGYkYBGmGWH19KcqlRxLi4z-kGAGFvVs,23733
1090
+ django_cfg-1.4.94.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
1091
+ django_cfg-1.4.94.dist-info/entry_points.txt,sha256=Ucmde4Z2wEzgb4AggxxZ0zaYDb9HpyE5blM3uJ0_VNg,56
1092
+ django_cfg-1.4.94.dist-info/licenses/LICENSE,sha256=xHuytiUkSZCRG3N11nk1X6q1_EGQtv6aL5O9cqNRhKE,1071
1093
+ django_cfg-1.4.94.dist-info/RECORD,,