# How to Create Custom Visualization Plugins (Chart Types) for Apache Superset

> Learn to create custom visualization plugins for Apache Superset. Extend ChartPlugin, define metadata, and register your chart type to enhance data exploration within Superset.

- Repository: [The Apache Software Foundation/superset](https://github.com/apache/superset)
- Tags: how-to-guide
- Published: 2026-03-03

---

**To create a custom visualization plugin for Apache Superset, extend the `ChartPlugin` class from `@superset-ui/core` to define metadata, loadChart, transformProps, and controlPanel, then register it in `MainPreset` with a unique key.**

Apache Superset’s visualization layer is built on a modular plugin architecture centered around the `ChartPlugin` class. Whether you need a proprietary chart type for internal metrics or a complex D3 visualization, the `apache/superset` repository provides a robust framework for extending the default chart library using patterns established by production plugins like Word Cloud.

## Understanding the ChartPlugin Architecture

Every custom chart in Superset is an instance of `ChartPlugin` that orchestrates five core responsibilities. In [`superset-frontend/plugins/plugin-chart-word-cloud/src/plugin/index.ts`](https://github.com/apache/superset/blob/main/superset-frontend/plugins/plugin-chart-word-cloud/src/plugin/index.ts), the `WordCloudChartPlugin` demonstrates this structure by wiring together metadata, data transformation, and UI controls.

The essential components include:

- **ChartMetadata**: Defines the display name, description, thumbnail, and tags visible in the chart picker.
- **loadChart**: A lazy-loading function that imports the React component responsible for rendering.
- **transformProps**: Converts the raw query results (`formData` and `queriesData`) into props consumed by your React component.
- **buildQuery**: (Optional) Customizes the SQL or JSON payload sent to the backend before execution.
- **Control Panel Definition**: Declares the form fields and UI controls available in the Explore view.

## Step-by-Step Implementation Guide

### 1. Scaffold the Plugin Structure

Superset includes a Yeoman-style generator located at `superset-frontend/packages/generator-superset`. Run the generator from the `superset-frontend` directory to create the boilerplate:

```bash
cd superset-frontend
npm run generate-plugin

```

This creates a new package under `superset-frontend/plugins/plugin-chart-<your-name>` containing [`package.json`](https://github.com/apache/superset/blob/main/package.json), TypeScript configuration, and stub files. The template reference is available at `superset-frontend/packages/generator-superset/generators/plugin-chart/templates/README.erb`.

### 2. Implement the ChartPlugin Class

Create a class extending `ChartPlugin<TFormData>` in [`src/plugin/index.ts`](https://github.com/apache/superset/blob/main/src/plugin/index.ts). This class constructor must pass an object containing metadata, the lazy loader, transformation logic, and the control panel configuration.

```ts
import { ChartMetadata, ChartPlugin } from '@superset-ui/core';
import transformProps from './transformProps';
import buildQuery from './buildQuery';
import controlPanel from './controlPanel';
import thumbnail from '../images/thumbnail.png';

const metadata = new ChartMetadata({
  name: t('My Fancy Chart'),
  description: t('A custom visualization for specialized analytics.'),
  thumbnail,
});

export default class MyFancyChartPlugin extends ChartPlugin<MyFormData> {
  constructor() {
    super({
      metadata,
      loadChart: () => import('../chart/MyFancyChart'),
      transformProps,
      buildQuery,
      controlPanel,
    });
  }
}

```

The Word Cloud plugin implementation at [`superset-frontend/plugins/plugin-chart-word-cloud/src/plugin/index.ts`](https://github.com/apache/superset/blob/main/superset-frontend/plugins/plugin-chart-word-cloud/src/plugin/index.ts) provides a concrete reference for this pattern.

### 3. Define the Control Panel

The control panel configuration determines which UI controls appear in the Explore view. Export a `ControlPanelConfig` from [`src/plugin/controlPanel.tsx`](https://github.com/apache/superset/blob/main/src/plugin/controlPanel.tsx) using components from `@superset-ui/chart-controls`.

```ts
import { ControlPanelConfig } from '@superset-ui/chart-controls';
import { t } from '@apache-superset/core';

export default {
  controlPanelSections: [
    {
      label: t('Query'),
      controlSetRows: [['metrics'], ['groupby']],
    },
    {
      label: t('Display'),
      controlSetRows: [
        ['color_scheme', 'label_type'],
      ],
    },
  ],
} as ControlPanelConfig;

```

See [`superset-frontend/plugins/plugin-chart-word-cloud/src/plugin/controlPanel.tsx`](https://github.com/apache/superset/blob/main/superset-frontend/plugins/plugin-chart-word-cloud/src/plugin/controlPanel.tsx) for a complete example including custom controls.

### 4. Write the transformProps Function

The `transformProps` function bridges Superset's query response and your React component's prop interface. It receives `chartProps` containing `width`, `height`, `formData`, and `queriesData`.

```ts
export default function transformProps(chartProps) {
  const { width, height, formData, queriesData } = chartProps;
  const { metric, colorScheme } = formData;
  const data = queriesData[0].data;

  return {
    width,
    height,
    data,
    metric,
    colorScheme,
  };
}

```

Reference the Word Cloud implementation at [`superset-frontend/plugins/plugin-chart-word-cloud/src/plugin/transformProps.ts`](https://github.com/apache/superset/blob/main/superset-frontend/plugins/plugin-chart-word-cloud/src/plugin/transformProps.ts) for data mapping logic.

### 5. (Optional) Implement Custom buildQuery

When the default query generation is insufficient, implement `buildQuery` to customize the payload sent to the backend. Use `buildQueryContext` and `PostProcessingOperator` from `@superset-ui/core`.

```ts
import { buildQueryContext, PostProcessingOperator } from '@superset-ui/core';

export default function buildQuery(formData) {
  return buildQueryContext(formData, baseQueryObject => [
    {
      ...baseQueryObject,
      post_processing: [
        {
          operation: PostProcessingOperator.PIVOT,
          options: {
            index: ['category'],
            columns: ['metric'],
            aggregates: { value: { operator: 'sum' } },
          },
        },
      ],
    },
  ]);
}

```

The Word Cloud plugin includes a minimal example at [`superset-frontend/plugins/plugin-chart-word-cloud/src/plugin/buildQuery.ts`](https://github.com/apache/superset/blob/main/superset-frontend/plugins/plugin-chart-word-cloud/src/plugin/buildQuery.ts).

### 6. Create the React Chart Component

The actual rendering logic lives in a React component, typically using libraries like D3 or ECharts. This component receives the props returned by `transformProps`.

```tsx
import React from 'react';

export default function MyFancyChart({ data, width, height, metric }) {
  return (
    <svg width={width} height={height}>
      {data.map((d, i) => (
        <circle
          key={i}
          cx={(i * 50) + 25}
          cy={height / 2}
          r={d[metric] / 10}
          fill="steelblue"
        />
      ))}
    </svg>
  );
}

```

Study [`superset-frontend/plugins/plugin-chart-word-cloud/src/chart/WordCloud.tsx`](https://github.com/apache/superset/blob/main/superset-frontend/plugins/plugin-chart-word-cloud/src/chart/WordCloud.tsx) for a production-grade D3 implementation.

### 7. Register the Plugin in MainPreset

To make the chart available in the UI, register it in [`superset-frontend/src/visualizations/presets/MainPreset.ts`](https://github.com/apache/superset/blob/main/superset-frontend/src/visualizations/presets/MainPreset.ts). Import your plugin and add it to the preset with a unique `VizType` key.

```ts
import { MyFancyChartPlugin } from '@superset-ui/plugin-chart-my-fancy';

new MyFancyChartPlugin().configure({ key: VizType.MyFancy }),

```

The Word Cloud registration appears at lines 144-147 in [`superset-frontend/src/visualizations/presets/MainPreset.ts`](https://github.com/apache/superset/blob/main/superset-frontend/src/visualizations/presets/MainPreset.ts).

## Complete Minimal Example: Hello World Chart

Below is a fully functional skeleton for a "Hello World" chart plugin that renders static text in an SVG.

**src/plugin/index.ts:**

```ts
import { ChartMetadata, ChartPlugin } from '@superset-ui/core';
import transformProps from './transformProps';
import controlPanel from './controlPanel';
import thumbnail from '../images/thumbnail.png';

const metadata = new ChartMetadata({
  name: t('Hello World'),
  description: t('A minimal example chart.'),
  thumbnail,
});

export default class HelloWorldChartPlugin extends ChartPlugin<any> {
  constructor() {
    super({
      metadata,
      loadChart: () => import('../chart/HelloWorld'),
      transformProps,
      controlPanel,
    });
  }
}

```

**src/plugin/controlPanel.tsx:**

```ts
import { ControlPanelConfig } from '@superset-ui/chart-controls';
import { t } from '@apache-superset/core';

export default {
  controlPanelSections: [
    {
      label: t('Query'),
      controlSetRows: [['metrics']],
    },
  ],
} as ControlPanelConfig;

```

**src/plugin/transformProps.ts:**

```ts
export default function transformProps({ width, height }) {
  return { width, height };
}

```

**src/chart/HelloWorld.tsx:**

```tsx
import React from 'react';

export default function HelloWorld({ width, height }) {
  return (
    <svg width={width} height={height}>
      <text x={width / 2} y={height / 2} textAnchor="middle" fontSize="24">
        Hello, Superset!
      </text>
    </svg>
  );
}

```

Finally, register the plugin in [`MainPreset.ts`](https://github.com/apache/superset/blob/main/MainPreset.ts):

```ts
import { HelloWorldChartPlugin } from '@superset-ui/plugin-chart-hello-world';

new HelloWorldChartPlugin().configure({ key: VizType.HelloWorld }),

```

Run `npm run dev` from `superset-frontend`, and "Hello World" will appear in the Viz Type dropdown.

## Summary

- **ChartPlugin Architecture**: Every custom visualization extends `ChartPlugin` and supplies metadata, `loadChart`, `transformProps`, an optional `buildQuery`, and a control panel definition.
- **File Locations**: Plugin code belongs in `superset-frontend/plugins/`, while registration occurs in [`superset-frontend/src/visualizations/presets/MainPreset.ts`](https://github.com/apache/superset/blob/main/superset-frontend/src/visualizations/presets/MainPreset.ts).
- **Generator Tool**: Use `npm run generate-plugin` to scaffold the directory structure and boilerplate.
- **Data Flow**: `transformProps` maps `formData` and `queriesData` to React props, while `buildQuery` optionally customizes the backend request.
- **Registration**: Each plugin requires a unique `VizType` key in `MainPreset` to appear in the chart creation UI.

## Frequently Asked Questions

### What is the ChartPlugin class in Superset?

The `ChartPlugin` class is the foundational abstraction in `@superset-ui/core` that encapsulates a visualization's metadata, configuration UI, data transformation logic, and rendering component. It acts as the bridge between Superset's backend data engine and the frontend React chart implementation.

### Where do I register a custom chart plugin?

Register custom plugins in [`superset-frontend/src/visualizations/presets/MainPreset.ts`](https://github.com/apache/superset/blob/main/superset-frontend/src/visualizations/presets/MainPreset.ts). Import your plugin class and instantiate it with `.configure({ key: VizType.YourUniqueKey })`, adding the result to the preset's plugin array. This registration makes the chart available in the Explore view's visualization type selector.

### How do I customize the query sent to the backend?

Implement a `buildQuery` function that receives `formData` and returns a query context object. Use `buildQueryContext` from `@superset-ui/core` to generate the base query, then modify it with custom `post_processing` steps or altered parameters. The Word Cloud plugin at [`superset-frontend/plugins/plugin-chart-word-cloud/src/plugin/buildQuery.ts`](https://github.com/apache/superset/blob/main/superset-frontend/plugins/plugin-chart-word-cloud/src/plugin/buildQuery.ts) demonstrates the basic structure.

### Can I use third-party libraries like D3 or ECharts?

Yes. The React component loaded by `loadChart` can import any visualization library. The Word Cloud plugin uses `d3-cloud`, while other core plugins use ECharts. Ensure you declare these dependencies in your plugin's [`package.json`](https://github.com/apache/superset/blob/main/package.json), and import them in your chart component file (e.g., [`src/chart/YourChart.tsx`](https://github.com/apache/superset/blob/main/src/chart/YourChart.tsx)).