The Superset extension architecture is designed to be modular, secure, and performant. This document provides a comprehensive overview of how extensions work and interact with the Superset host application.
Superset's core remains minimal, with features delegated to extensions wherever possible. Built-in features use the same APIs as external extensions, ensuring API quality through dogfooding.
All extension points are clearly defined and documented. Extensions declare their capabilities in metadata files, enabling predictable lifecycle management.
Public interfaces follow semantic versioning, ensuring backward compatibility and safe evolution of the platform.
Extensions load only when needed, minimizing performance impact and resource consumption.
Architecture patterns and APIs are reusable across different Superset modules, promoting consistency.
The system evolves based on real-world feedback, with new extension points added as needs emerge.
graph TB subgraph "Superset Host Application" Core[Core Application] API[Extension APIs] Loader[Extension Loader] Manager[Extension Manager] end subgraph "Core Packages" FrontendCore["@apache-superset/core<br/>(Frontend)"] BackendCore["apache-superset-core<br/>(Backend)"] CLI["apache-superset-extensions-cli"] end subgraph "Extension" Metadata[extension.json] Frontend[Frontend Code] Backend[Backend Code] Bundle[.supx Bundle] end Core --> API API --> FrontendCore API --> BackendCore Loader --> Manager Manager --> Bundle Frontend --> FrontendCore Backend --> BackendCore CLI --> Bundle
The Superset host application provides:
Each extension consists of:
extension.json): Declares capabilities and requirements.supx): Packaged distribution formatExtensions use Webpack Module Federation for dynamic loading:
// Extension webpack.config.js new ModuleFederationPlugin({ name: 'my_extension', filename: 'remoteEntry.[contenthash].js', exposes: { './index': './src/index.tsx', }, externals: { '@apache-superset/core': 'superset', }, shared: { react: { singleton: true }, 'react-dom': { singleton: true }, } })
This allows:
// Extension registered with host extensionManager.register({ name: 'my-extension', version: '1.0.0', manifest: manifestData });
// activate() called when extension loads export function activate(context: ExtensionContext) { // Register contributions const disposables = []; // Add panel disposables.push( context.core.registerView('my-panel', MyPanel) ); // Register command disposables.push( context.commands.registerCommand('my-command', { execute: () => { /* ... */ } }) ); // Store for cleanup context.subscriptions.push(...disposables); }
// Automatic cleanup of registered items export function deactivate() { // context.subscriptions automatically disposed // Additional cleanup if needed }
Extensions can add panels and UI components:
{ "views": { "sqllab.panels": [{ "id": "my-panel", "name": "My Panel", "icon": "ToolOutlined" }] } }
Define executable actions:
{ "commands": [{ "command": "my-extension.run", "title": "Run Analysis", "icon": "PlayCircleOutlined" }] }
Add items to existing menus:
{ "menus": { "sqllab.editor": { "primary": [{ "command": "my-extension.run", "when": "editorHasSelection" }] } } }
Register backend REST endpoints:
from superset_core.api import rest_api @rest_api.route('/my-endpoint') def my_endpoint(): return {'data': 'value'}
# superset_config.py ENABLE_EXTENSIONS = True LOCAL_EXTENSIONS = ['/path/to/extension']