Socket
Book a DemoInstallSign in
Socket

@djangocfg/ext-base

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@djangocfg/ext-base

Base utilities and common code for DjangoCFG extensions

latest
Source
npmnpm
Version
1.0.6
Version published
Maintainers
1
Created
Source

DjangoCFG Extension Preview

📦 View in Marketplace📖 Documentation⭐ GitHub

@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:

# Create a new extension with interactive wizard
djangocfg-ext create

# Quick test extension (auto-cleanup + unique name)
djangocfg-ext test

# List all extensions in workspace
djangocfg-ext list

# Show extension info
djangocfg-ext info <extension-name>

# Show help
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
  • Playground environment with Next.js 15 for rapid development
  • Auto-dependency installation and type checking
  • Smart workspace detection for monorepos

Quick Start

1. Create extension metadata

Use the createExtensionConfig helper to automatically pull data from package.json:

// src/config.ts
import { createExtensionConfig } from '@djangocfg/ext-base';
import packageJson from '../package.json';

export const extensionConfig = createExtensionConfig(packageJson, {
  name: 'my-extension',
  displayName: 'My Extension',
  icon: 'Rocket', // Lucide icon name
  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

// src/contexts/MyExtensionProvider.tsx
'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';

export default function RootLayout({ children }) {
  return (
    <MyExtensionProvider>
      {children}
    </MyExtensionProvider>
  );
}

Development Workflow

Every extension created with the CLI includes a playground - a Next.js 15 development environment for rapid testing and iteration.

Starting the Playground

cd your-extension
pnpm dev:playground

This command:

  • ✅ Automatically builds your extension
  • ✅ Starts Next.js dev server on port 3333
  • ✅ Opens browser automatically
  • ✅ Hot-reloads on source changes

Playground Features

  • Next.js 15 App Router with React 19
  • Tailwind CSS v4 pre-configured
  • BaseApp wrapper with theme, auth, and SWR
  • Auto-build extension before starting (via predev script)
  • Auto-open browser when dev server is ready
  • Hot reload for instant feedback

Building for Production

# Build extension
pnpm build

# Build playground
pnpm build:playground

# Type check
pnpm check

Smart Provider Pattern

Extensions support a Smart Provider Pattern that allows components to work both standalone and with manual provider wrapping.

Using withSmartProvider

Create self-contained components that automatically wrap themselves with the provider when needed:

import { withSmartProvider } from '@your-org/my-extension';

// Your component
function MyComponent() {
  const { data } = useMyExtension();
  return <div>{data}</div>;
}

// Wrap with smart provider
export const MySmartComponent = withSmartProvider(MyComponent);

Usage:

// Works standalone (auto-wrapped)
<MySmartComponent />

// Also works with manual provider (shares context)
<MyExtensionProvider>
  <MySmartComponent />
  <MySmartComponent />
</MyExtensionProvider>

Benefits:

  • ✅ Components work out-of-the-box without provider boilerplate
  • ✅ Multiple components can still share context when manually wrapped
  • ✅ Best of both worlds - simplicity and flexibility

When to use:

  • Library components that should "just work"
  • Components that might be used in isolation
  • Reducing boilerplate for simple use cases

When to use manual provider:

  • Multiple components need to share state
  • Performance optimization (single provider instance)
  • Explicit context boundaries

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, {
  // Required fields
  name: 'my-extension',
  displayName: 'My Extension',
  icon: 'Package', // Lucide icon name
  category: 'utilities', // 'forms' | 'payments' | 'content' | 'support' | 'utilities' | 'analytics' | 'security' | 'integration' | 'other'
  features: ['Feature list for marketplace'],

  // Optional fields
  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-newsletterdjangocfg-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';

// Handles API URL, static build detection, and shared auth automatically
export const apiMyExtension = createExtensionAPI(API);

Pagination Hooks

import { usePagination, useInfinitePagination } from '@djangocfg/ext-base/hooks';

// Standard pagination
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,
});

// Infinite scroll
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

ExportDescriptionUsage
@djangocfg/ext-baseServer-safe exports (types, environment, API factory, logger, error handling)Server & client components
@djangocfg/ext-base/hooksClient-only exports (ExtensionProvider, pagination hooks, context factory)Client components only
@djangocfg/ext-base/authAuth re-exports (useAuth, types)Client components only
@djangocfg/ext-base/apiAPI utilities (createExtensionAPI, getSharedAuthStorage)Server & client components

For your own extensions:

Extension templates automatically export:

  • extensionConfig - Extension metadata
  • [Name]Provider - Main provider component (wraps ExtensionProvider)
  • use[Name] - Context hook (required provider)
  • use[Name]Optional - Context hook (optional provider)
  • withSmartProvider - HOC for self-contained components

Server-safe imports:

  • Use @your-org/ext-name/config to import extension metadata without loading React components
  • This is recommended for server components and build tools

Extension Categories

The package exports a standardized list of extension categories:

import { EXTENSION_CATEGORIES } from '@djangocfg/ext-base';

// Array of { title: string, value: ExtensionCategory }
EXTENSION_CATEGORIES.forEach(category => {
  console.log(category.title, category.value);
  // Forms, forms
  // Payments, payments
  // Content, content
  // Support, support
  // Utilities, utilities
  // Analytics, analytics
  // Security, security
  // Integration, integration
  // Other, other
});

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 {
  // Extension configuration
  ExtensionMetadata,
  ExtensionConfigInput,
  ExtensionCategory,
  ExtensionExample,

  // Provider
  ExtensionProviderProps,

  // Pagination
  PaginatedResponse,
  PaginationParams,
  PaginationState,
  InfinitePaginationReturn,

  // Utilities
  ExtensionLogger,
  ExtensionError,
} from '@djangocfg/ext-base';

Best Practices

Configuration & Metadata

  • Use createExtensionConfig helper to maintain Single Source of Truth from package.json
  • Use Lucide icon names (not emoji) for icon field
  • Include comprehensive features list for marketplace visibility
  • Provide code examples with proper syntax highlighting
  • Include a preview.png file in your extension root (1200x630px recommended)
  • List preview.png in your package.json files array for npm publication

Development

  • Use the playground for rapid development (pnpm dev:playground)
  • Test your components in isolation before integrating
  • Run type checks before building (pnpm check)
  • Use createExtensionLogger with consistent tags for structured logging

Architecture

  • Always wrap your extension with ExtensionProvider for proper registration
  • Export main provider as [Name]Provider (not [Name]ExtensionProvider)
  • Use withSmartProvider for components that should work standalone
  • Prefer manual provider wrapping when components need shared state
  • Use provided pagination hooks for consistent data fetching
  • Separate client-only code appropriately

Publishing

  • Test with pnpm build before publishing
  • Verify preview image is accessible via unpkg
  • Ensure all peer dependencies are correctly listed
  • Include clear usage examples in README

License

MIT

Keywords

django

FAQs

Package last updated on 15 Dec 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts