@djangocfg/ext-base
Base utilities and common code for building DjangoCFG extensions.
Part of DjangoCFG — modern Django framework for production-ready SaaS applications.
What is this?
@djangocfg/ext-base provides the foundation for DjangoCFG extensions with:
- Extension registration system and metadata tracking
- React hooks for pagination, infinite scroll, and data fetching
- Environment utilities (isDevelopment, isProduction, isStaticBuild)
- Type-safe context helpers and logger utilities
- Auth integration and API factory
- CLI tool for managing extensions
Used internally by official extensions (newsletter, payments, support, leads, knowbase) and for building custom extensions.
Install
pnpm add @djangocfg/ext-base
CLI Usage
The package includes a CLI tool for creating new DjangoCFG extensions:
djangocfg-ext create
djangocfg-ext help
The CLI will guide you through creating a new extension with proper structure and configuration using the createExtensionConfig helper.
Features:
- Interactive prompts for package name, description, icon, and category
- Automatic npm registry validation to prevent duplicate package names
- Support for both scoped (
@my-org/my-extension) and unscoped (my-extension) package names
- Template generation with proper placeholder replacement
Quick Start
1. Create extension metadata
Use the createExtensionConfig helper to automatically pull data from package.json:
import { createExtensionConfig } from '@djangocfg/ext-base';
import packageJson from '../package.json';
export const extensionConfig = createExtensionConfig(packageJson, {
name: 'my-extension',
displayName: 'My Extension',
icon: 'Rocket',
category: 'utilities',
features: [
'Feature 1',
'Feature 2',
'Feature 3',
],
minVersion: '2.0.0',
examples: [
{
title: 'Basic Usage',
description: 'How to use this extension',
code: `import { MyComponent } from '@your-org/my-extension';`,
language: 'tsx',
},
],
});
This automatically imports from package.json:
- version
- author
- description
- license
- homepage
- githubUrl (from repository)
- keywords
- peerDependencies
2. Create extension provider
'use client';
import { ExtensionProvider } from '@djangocfg/ext-base/hooks';
import { extensionConfig } from '../config';
export function MyExtensionProvider({ children }) {
return (
<ExtensionProvider metadata={extensionConfig}>
{children}
</ExtensionProvider>
);
}
3. Use in your app
import { MyExtensionProvider } from '@your-org/my-extension/hooks';
export default function RootLayout({ children }) {
return (
<MyExtensionProvider>
{children}
</MyExtensionProvider>
);
}
Core Features
Extension Config Helper
The createExtensionConfig helper creates a typed extension configuration by combining package.json data with manual metadata:
import { createExtensionConfig, type ExtensionConfigInput } from '@djangocfg/ext-base';
import packageJson from '../package.json';
export const extensionConfig = createExtensionConfig(packageJson, {
name: 'my-extension',
displayName: 'My Extension',
icon: 'Package',
category: 'utilities',
features: ['Feature list for marketplace'],
minVersion: '2.0.0',
githubStars: 100,
examples: [
{
title: 'Example title',
description: 'Example description',
code: 'import { Component } from "@your-org/my-extension";',
language: 'tsx',
},
],
});
Automatically imported from package.json:
version - Package version
author - Author name (from string or object)
description - Package description
license - License type
homepage - Homepage URL
githubUrl - Repository URL
keywords - Keywords array
peerDependencies - Peer dependencies (workspace:* auto-replaced with latest)
packageDependencies - Dependencies from package.json (workspace:* auto-replaced with latest)
Auto-generated:
npmUrl - npm package URL (https://www.npmjs.com/package/[name])
marketplaceId - URL-safe ID (@ and / replaced with -), e.g. @djangocfg/ext-newsletter → djangocfg-ext-newsletter
marketplaceUrl - Marketplace URL (only for official @djangocfg extensions): https://hub.djangocfg.com/extensions/[marketplaceId]
installCommand - pnpm install command
downloadUrl - npm tarball download URL
preview - Preview image URL (https://unpkg.com/[name]@latest/preview.png)
tags - Same as keywords
Note: All workspace:* dependencies are automatically replaced with latest for marketplace display.
Environment Configuration
import { isDevelopment, isProduction, isStaticBuild } from '@djangocfg/ext-base';
if (isDevelopment) {
console.log('Running in development mode');
}
API Factory
Create extension API instances with automatic configuration:
import { API } from './generated/ext_myextension';
import { createExtensionAPI } from '@djangocfg/ext-base/api';
export const apiMyExtension = createExtensionAPI(API);
import { usePagination, useInfinitePagination } from '@djangocfg/ext-base/hooks';
const { items, page, totalPages, goToPage, nextPage, prevPage } = usePagination({
keyPrefix: 'articles',
fetcher: async (page, pageSize) => {
const response = await api.articles.list({ page, page_size: pageSize });
return response.data;
},
pageSize: 20,
});
const { items, isLoading, hasMore, loadMore } = useInfinitePagination({
keyPrefix: 'articles',
fetcher: async (page, pageSize) => api.articles.list({ page, page_size: pageSize }).then(r => r.data),
pageSize: 20,
});
Type-Safe Context Creation
import { createExtensionContext } from '@djangocfg/ext-base/hooks';
interface MyContextValue {
data: any[];
refresh: () => void;
}
const { Provider, useContext: useMyContext } = createExtensionContext<MyContextValue>({
displayName: 'MyContext',
errorMessage: 'useMyContext must be used within MyProvider',
});
Logger
import { createExtensionLogger } from '@djangocfg/ext-base';
const logger = createExtensionLogger({ tag: 'my-extension' });
logger.info('Extension initialized');
logger.error('Operation failed', error);
logger.success('Completed!');
Auth Integration
import { useAuth } from '@djangocfg/ext-base/auth';
function MyComponent() {
const { user, isAuthenticated, login, logout } = useAuth();
return isAuthenticated ? (
<div>Welcome, {user?.email}</div>
) : (
<button onClick={login}>Login</button>
);
}
Package Exports
@djangocfg/ext-base | Server-safe exports (types, environment, API factory, logger, error handling) | Server & client components |
@djangocfg/ext-base/hooks | Client-only exports (ExtensionProvider, pagination hooks, context factory) | Client components only |
@djangocfg/ext-base/auth | Auth re-exports (useAuth, types) | Client components only |
@djangocfg/ext-base/api | API utilities (createExtensionAPI, getSharedAuthStorage) | Server & client components |
For your own extensions:
- Use
@your-org/ext-name/config to import extension metadata without loading React components (server-safe)
- This is the recommended way to import
extensionConfig in server components and build tools
Extension Categories
The package exports a standardized list of extension categories:
import { EXTENSION_CATEGORIES } from '@djangocfg/ext-base';
EXTENSION_CATEGORIES.forEach(category => {
console.log(category.title, category.value);
});
Available categories:
forms - Forms, CRM, Lead Management
payments - Payment Processing, Billing
content - Content Management, Marketing
support - Support, Helpdesk, Tickets
utilities - Tools, Base, Infrastructure
analytics - Analytics, Tracking, Monitoring
security - Security, Authentication, Authorization
integration - Third-party Integrations
other - Other/Uncategorized
TypeScript Types
import type {
ExtensionMetadata,
ExtensionConfigInput,
ExtensionCategory,
ExtensionExample,
ExtensionProviderProps,
PaginatedResponse,
PaginationParams,
PaginationState,
InfinitePaginationReturn,
ExtensionLogger,
ExtensionError,
} from '@djangocfg/ext-base';
Best Practices
- Use
createExtensionConfig helper to maintain Single Source of Truth from package.json
- Always wrap your extension with
ExtensionProvider for proper registration
- Use Lucide icon names (not emoji) for
icon field
- Include a
preview.png file in your extension root (1200x630px recommended) - it will be automatically served via unpkg
- Include comprehensive
features list for marketplace visibility
- Provide code
examples with proper syntax highlighting
- Use provided pagination hooks for consistent data fetching
- Use
createExtensionLogger with consistent tags for structured logging
- Separate client-only code using
/hooks entry point
- List
preview.png in your package.json files array for npm publication
License
MIT
Links