Develop custom charts

Updated at:

When built-in charts do not meet your business visualization needs, you can develop custom charts for use in AIPro visual reports. This capability extends the available chart types and helps you present business data more accurately. This topic describes two development methods to help you quickly develop and upload custom charts to the platform.

Prerequisites

  • Purchase: Your organization has purchased Quick BI AIPro.

  • Permissions: Only users with AIPro centralized management permissions can access the Admin Console to upload custom charts. For details about permission settings, see user permissions.

Development methods

You can choose either of the following methods to develop a custom chart based on your needs.

Method

Best for

Key features

Method 1: Skill-assisted development

Business users and BI administrators with no coding experience.

Use natural language to direct the AI to automatically generate, debug, build, and upload chart code.

Method 2: Manual code development

Technical users with front-end development experience.

Write code by hand and upload the chart from the Chart Management page in the Admin Console.

Method 1: Skill-assisted development

Use the quickbi-custom-ai-chart-builder Skill provided by Quick BI to complete the entire chart development process through natural language conversations in your local IDE. You do not need to write code manually; the AI guides you through requirements analysis, code generation, real-time debugging, building, packaging, and uploading.

Prepare your local environment

Before you start developing charts, make sure you have completed the following preparations in your local environment.

  • Install Node.js: Download and install Node.js version 22.20.0 or later from the official website.

  • npm source: Use the official npm source: https://registry.npmjs.org.

  • Install an AI-powered programming tool: Download and install a local AI-powered programming tool that supports Skill and MCP functions, such as Qoder IDE.

Procedure

To develop a custom chart with Skill assistance, follow these steps: Install the Skill > Connect to MCP > Develop the chart > Debug in real time > Build and upload. The following sections describe each step in detail.

Step 1: Install the Skill

Run the following command in your local terminal to install the quickbi-custom-ai-chart-builder Skill provided by Quick BI.

npx skills add https://github.com/quick-bi/skills.git --skill quickbi-custom-ai-chart-builder

Step 2: Connect to MCP

Note

You only need to configure the MCP connection once. This configuration can be reused in later sessions. If you have already configured Quick BI MCP in your local IDE, you can skip this step.

The MCP service acts as a bridge between the Skill and the Quick BI platform, enabling tasks like retrieving a dataset, local preview, and chart upload. The first time you use the Skill, the AI guides you through configuring the MCP service. After configuration, you can develop, debug, and upload charts automatically through MCP. Follow these steps to configure the service.

  1. Obtain configuration credentials

    1. Log in to Quick BI AIPro, hover over your profile picture in the lower-left corner of the page, and click Personal Settings.AIPro 左下角个人头像与下拉菜单中的个人设置入口

    2. In the Personal Settings dialog box, on the Account Information tab, click Get Personal Identification Code.

      个人设置弹窗的账户信息区,红框为获取个人识别码按钮

    3. On the Personal Identification Code panel, find the MCP Installation card and click Copy. The configuration information is copied to your clipboard. Paste it into the chat dialog in your local IDE, such as Qoder IDE, and the client will automatically apply the Quick BI MCP service configuration.个人识别码区域 Skill/MCP 一键安装入口 The copied configuration information includes the following:

      Configuration

      Description

      api_key

      An identifier for the caller.

      api_secret

      The secret key paired with the api_key.

      user_token

      A token representing the current user that defines the access scope for data and assets.

      server_domain

      The Quick BI service endpoint. For the public cloud, this is https://bi.aliyun.com.

      Important

      The api_key and api_secret are sensitive credentials. Share them only with trusted systems and authorized personnel. Keep them secure and prevent disclosure. If you suspect a leak, rotate your credentials immediately.

    4. Paste the copied configuration information into the IDE chat dialog and send it. The Skill automatically reads this information to complete the configuration.

  2. Configure the MCP Server structure (optional): If your IDE does not support automatic configuration, you can enter the information manually.

    {
      "mcpServers": {
        "quickbi": {
          "url": "<server_domain>",
          "type": "https",
          "headers": {
            "x-quickbi-server-domain": "<server_domain>",
            "x-quickbi-api-key": "<api_key>",
            "x-quickbi-api-secret": "<api_secret>"
          }
        }
      }
    }            
  3. Load and verify: After saving the configuration, reload the MCP Server or restart the IDE. Confirm that the Quick BI Skill appears in the tool list. If it is unavailable or you encounter connection failures, obtain the configuration information again and retry.

Step 3: Develop the chart

In your local IDE, call the Quick BI custom chart Skill and use natural language to describe your chart requirements to start the development process. For example, "Help me develop a radial bar chart."

The AI will confirm details with you, such as chart type, data fields, and interaction requirements, and then generates a chart implementation plan (PLAN.md) for your review. After you confirm the plan, the AI automatically generates the chart code.Skill 对话:AI 生成图表实现计划并列出待办事项

Step 4: Real-time debugging

After the chart files are generated, the AI automatically opens a real-time debugging page in your local browser to preview the custom chart. During debugging, the AI automatically retrieves a suitable dataset from My Data to render the chart. You can also specify or change the dataset at any time through conversations in the IDE.

By default, the real-time debugging page only displays the single custom chart that was generated. To test query controls, linkage effects with other charts, or to verify the chart's behavior when filtered or controlled, you can instruct the AI directly in the IDE. For example, "Add a query control and a linked chart for this chart." The AI will automatically generate and run the relevant code and update the debugging page. Refresh the page to see the effects. Continue to adjust the style, color scheme, interactions, and linkage logic using natural language until the custom chart meets your expectations.

Note

Before entering real-time debugging, the AI first starts a local preview service on your computer. The first time you open it, your browser may show a "Connection is not secure" warning. This is expected because the debugging service uses a local certificate and does not indicate a problem with the chart. Follow the prompts to proceed and accept the certificate, then return to and refresh the debugging page to preview it correctly.image

image

image

Step 5: Build and upload

Note

Make sure your Quick BI AIPro account has AIPro management permissions. Otherwise, the AI cannot upload the chart.

When the chart meets your expectations, you can tell the AI in the IDE, "The result is satisfactory, you can upload it to the platform now." The AI will then guide you through building, packaging, and uploading the chart to the Quick BI AIPro platform through the MCP interface.

After a successful upload, the chart is visible to all users and enabled by default. It is also automatically installed in My Charts. Other members of your organization can browse and install the chart from the Chart Marketplace. The AI will then automatically select this chart when its name is mentioned or when a user's request semantically matches its description.AIPro 生成 AI 报表:竞争对手分析报表中使用环形柱图展示胜率排名

Method 2: Manual code development

Developers write chart code directly using the scaffolding project provided by Quick BI. After debugging, they upload and configure the chart in the Quick BI AIPro Admin Console. This method requires manual coding and is suitable for technical users with front-end development experience.

Prepare your local environment

  • Install Node.js: Download and install Node.js version 22.20.0 or later from the official website.

  • npm source: Use the official npm source: https://registry.npmjs.org.

  • Install a local development tool: Install a local development tool of your choice, such as VS Code.

Procedure

The overall process for developing a custom chart by writing code is: Create a project > Configure the meta file (data contract) > Write the chart code > Configure external dependencies > Build and upload. The following sections describe each step in detail.

Step 1: Create a project

  1. Open your local terminal, navigate to the folder where you want to create the project, and run the following command to create a chart project from the Quick BI scaffolding.

    • React version

      npx -y --registry=https://registry.npmjs.org create-qbi-app@latest my-chart --template ai-chart-react-ts
    • Vanilla version

      npx -y --registry=https://registry.npmjs.org create-qbi-app@latest my-chart --template ai-chart-vanilla-ts
    Important

    The chart name must start with a lowercase letter and can only contain lowercase letters, numbers, underscores (_), or hyphens (-). It must be at least two characters long.

    The resulting project structure is as follows:

    my-chart/
    ├── src/
    │   ├── meta.ts          # Data contract definition
    │   ├── index.ts          # Entry point (exports lifecycle functions)
    │   ├── Component.tsx     # Main component (React version)
    │   └── Component.scss    # Styles (optional)
    ├── qbi.config.ts         # Build configuration
    ├── package.json
    └── tsconfig.json
  2. Run the following command to download and install the project's dependencies.

    cd my-chart && npm install --registry=https://registry.npmjs.org

Step 2: Configure meta file (data contract)

In your local development tool, find and open the meta.ts file in the project. This file defines the chart's data contract, which specifies what data (dimensions or measures) the chart requires, whether the data is mandatory, and limits on the number of data fields.

Note

AI-version custom charts use the AIComponentMeta type and only declare dataSchema (data field contract). You do not need to declare a style panel. The chart's data contract is exported through defineMeta.

The following is a code sample:

// src/meta.ts
import type { Interfaces } from '@quickbi/bi-open-react-sdk';
import { defineMeta } from '@quickbi/bi-open-react-sdk';

export default defineMeta<Interfaces.AIComponentMeta>({
  dataSchema: {
    areas: [
      {
        id: 'area_row',                           // Area ID, key in DSL and encoding
        name: 'Dimension',
        description: 'Category axis, bind dimension fields',        // AI semantic description for AI recall
        queryAxis: 'row',                          // Query axis: row / column / drill / filters
        rule: {
          required: true,                          // Specifies whether the field is required
          maxColNum: 1,                            // Maximum number of allowed fields
          fieldTypes: ['dimension'],               // Allowed field types
        },
      },
      {
        id: 'area_column',
        name: 'Measure',
        description: 'Value axis, bind measure fields',
        queryAxis: 'column',
        rule: {
          required: true,
          maxColNum: 3,
          fieldTypes: ['measure'],
        },
      },
    ],
  },
});

Field

Required

Type

Description

dataSchema.areas

Yes

DataSchemaArea[]

A list of field areas that define which dimensions and measures the chart requires.

areas[].id

Yes

string

The unique identifier for the area. It is also the key for DSL encoding and the component's props.encoding.

areas[].name

Yes

string

The display name of the area.

areas[].nameTip

No

string

Tooltip information for the area name.

areas[].description

No

(Recommended)

string

This description helps the AI automatically match fields when generating reports.

areas[].queryAxis

Yes

'row' | 'column' | 'drill' | 'filters'

The type of query axis.

  • row: dimension axis

  • column: measure axis

  • drill: drill-down axis

  • filters: filter

areas[].rule.required

Yes

boolean

Specifies whether the field is required.

  • true: Required

  • false: Not required

areas[].rule.maxColNum

Yes

number

The maximum number of fields allowed in the area.

areas[].rule.fieldTypes

Yes

('dimension' | 'measure')[]

The types of fields allowed in the area.

  • dimension: dimension

  • measure: measure

areas[].rule.fieldGroupTypes

No

string[]

Allowed field group types.

areas[].rule.fieldCollectionTypes

No

string[]

Allowed field collection types.

areas[].rule.placeholder

No

string

Placeholder text.

Step 3: Write chart code

Implement the chart in the Component.tsx file and export it from the index.ts file. This process transforms incoming data into a rendered chart. The following are code samples:

Note

See Type reference in this topic to learn more about the data structures and parameter specifications to follow when developing custom chart components.

  • React version

    The React component directly receives AIComponentProps and is exported using the createBIComponent wrapper.

    // src/Component.tsx
    import React, { useRef, useEffect } from 'react';
    import type { Interfaces } from '@quickbi/bi-open-react-sdk';
    
    const MyChart: React.FC<Interfaces.AIComponentProps> = React.memo(
      ({ data, encoding, dispatch }) => {
        const containerRef = useRef<HTMLDivElement>(null);
    
        // Read fields from encoding
        const categoryField = encoding.area_row?.[0];      // Dimension field name
        const valueFields = encoding.area_column ?? [];     // Measure field name array
        const rows = data?.values ?? [];                    // Data rows
    
        useEffect(() => {
          if (!containerRef.current || rows.length === 0) return;
          // Initialize the chart here (for example, by using echarts.init or pure SVG rendering)
          // ...
        }, [data, encoding]);
    
        return <div ref={containerRef} style={{ width: '100%', height: '100%' }} />;
      },
    );
    
    export default MyChart;
    // src/index.ts
    import { createBIComponent } from '@quickbi/bi-open-react-sdk';
    import Component from './Component';
    
    export const { bootstrap, mount, unmount, update } = createBIComponent({
      element: Component,
    });
  • Vanilla version

    The Vanilla component uses a class style, is wrapped with LifecycleProps, and reads business data from props.customProps.

    // src/Component.ts
    import type { Interfaces } from '@quickbi/bi-open-sdk';
    
    class MyChart {
      mount(props: Interfaces.LifecycleProps<Interfaces.AIComponentProps>) {
        this.render(props);
      }
    
      update(props: Interfaces.LifecycleProps<Interfaces.AIComponentProps>) {
        this.render(props);
      }
    
      umount(props: Interfaces.LifecycleProps<Interfaces.AIComponentProps>) {
        props.container?.replaceChildren();
      }
    
      private render(props: Interfaces.LifecycleProps<Interfaces.AIComponentProps>) {
        const { data, encoding } = props.customProps!;
        const categoryField = encoding.area_row?.[0];
        const valueFields = encoding.area_column ?? [];
        const rows = data?.values ?? [];
    
        props.container!.textContent =
          `${rows.length} rows: ${Object.keys(encoding).join(', ')}`;
      }
    }
    
    export default MyChart;
    // src/index.ts
    import { createBIComponent } from '@quickbi/bi-open-sdk';
    import Component from './Component';
    
    export const { bootstrap, mount, unmount, update } = createBIComponent({
      element: Component,
    });

Step 4: Configure external dependencies

If your chart depends on a third-party library, such as ECharts, declare it as an external in the qbi.config.ts file. You must then provide its CDN URL when uploading the chart in the AIPro Admin Console.

The following is a code sample:

  • qbi.config.ts

    import { defineConfig } from '@quickbi/qbi-dev-tools';
    
    export default defineConfig({
      entry: {
        BIComponentMeta: './src/meta.ts',
        BIComponent: './src/index.ts',
      },
      devServer: {
        port: 8001,
        host: '127.0.0.1',
        server: { type: 'https' },
      },
      externals: {
        // Host built-in libraries (pre-configured in the template, no CDN URL required)
        lodash: '_',
        react: 'React',
        'react-dom': 'ReactDOM',
        moment: 'moment',
    
        // Third-party chart libraries (require a CDN URL)
        echarts: 'echarts',
      },
    });
    
    Important

    The @quickbi/bi-open-sdk and @quickbi/bi-open-react-sdk packages must be included in the chart bundle and cannot be placed in externals.

  • External Assets (third-party library CDN URLs)

    For each external dependency that is not built into the host, you must provide its CDN URL during upload. Use the format { name, global, url }:

    Dependency

    Externals

    External assets

    ECharts

    { echarts: 'echarts' }

    [{ name: 'echarts', global: 'echarts', url: 'https://cdn.jsdelivr.net/npm/echarts@5.5.0/dist/echarts.min.js' }]

    Vega Embed

    { 'vega-embed': 'vegaEmbed' }

    [{ name: 'vega-embed', global: 'vegaEmbed', url: 'https://cdn.jsdelivr.net/npm/vega-embed@6.24.0/build/vega-embed.min.js' }]

    React / lodash / moment

    Pre-configured in template

    Not required (built into the host)

Step 5: Build and upload

After writing the code, preview and debug the chart in your local browser. Once satisfied, build the code package and upload it to the Quick BI AIPro platform for use.

  1. Debug: Run the following command in the project's root directory to start the local service. You can then view the chart's implementation and debug it as needed.

    qdt start
  2. Package and build: After confirming that the chart works as expected, run the following commands to build the chart code package.

    qdt build    # → dist/main.js + dist/meta.js + dist/main.css (optional)
    qdt bundle   # → project root directory/{name}-{version}.zip
    Note

    Before building, check the following:

    • dist/main.js and dist/meta.js exist and are not empty.

    • The total size of the build artifacts is 10 MB or less. If it exceeds this limit, check if you have forgotten to declare a third-party library in externals.

  3. Upload manually

    1. Log in to the Quick BI AIPro Admin Console, go to Extension Management > Chart Management, and click Add Chart in the upper-right corner of the page.image

    2. In the Upload Chart dialog box, configure the chart's information.image

      Parameter

      Description

      Chart name

      Enter a custom name for the chart. You can name it based on its business purpose or core function. Make sure the name is unique within your organization.

      Chart description

      Enter a description for the chart, such as its usage scenarios or business functions. This information helps team members and the AI understand and use the chart correctly. The description must be 200 characters or less.

      Thumbnail

      Upload a thumbnail for the chart to provide a visual representation of its appearance. The file can be in PNG, JPG, JPEG, or SVG format, and its size must be 200 KB or less.

      Dependent third-party libraries

      If the chart uses a third-party library, such as ECharts, click Add to enter the library's information.image

      • Third-party library name: The package name from the import statement (e.g., echarts in import * as echarts from "echarts").

      • Module export name: The name of the global variable for a third-party library, for example, echarts in window.echarts.

      • Third-party library CDN path: The CDN URL for the library. It must be a UMD module.

      Code package

      The packaged and built chart code file. You can add it to the upload area by clicking or dragging. The file must be in .zip format and its size must be 10 MB or less.

    3. After configuring the information, click Upload. After a successful upload, the chart is visible to all users and enabled by default. It is also automatically installed in My Charts. Other members of your organization can browse and install the chart from the Chart Marketplace. The AI will then automatically select this chart when its name is mentioned or when a user's request semantically matches its description.AIPro 生成 AI 报表:竞争对手分析报表中使用环形柱图展示胜率排名

Type reference

The following is a type reference for Quick BI AIPro custom charts. It helps you understand the data structures and parameter specifications to follow when developing custom chart components.

AIComponentMeta

Defines the chart's field data contract. The source of truth is in @quickbi/bi-types.

interface AIComponentMeta {
  /** Data contract */
  dataSchema?: AIComponentMetaDataSchema;
}

interface AIComponentMetaDataSchema {
  areas: DataSchemaArea[];
}

interface DataSchemaArea {
  id: string;                                          // Unique identifier for the area
  name: string;                                        // Display name of the area
  nameTip?: string;                                    // Tooltip for the name
  description?: string;                                // AI semantic description (recommended)
  queryAxis: 'row' | 'column' | 'drill' | 'filters';  // Query axis
  rule: DataSchemaAreaRule;                            // Field rules
}

interface DataSchemaAreaRule {
  required?: boolean;                                  // Specifies whether the field is required
  maxColNum?: number;                                  // Maximum number of fields
  placeholder?: string;                                // Placeholder text
  fieldTypes?: ('dimension' | 'measure')[];            // Field types
  fieldGroupTypes?: string[];                          // Field group types
  fieldCollectionTypes?: string[];                     // Field collection types
}

AIComponentProps

The shape of the runtime props data passed from the host to the chart.

interface AIComponentProps {
  /** Component data: an array of rows, where each row is a Record<string, unknown> */
  data: { values: ReadonlyArray<Readonly<Record<string, unknown>>> };

  /** Field encoding mapping: area id → array of field names */
  encoding: Readonly<Record<string, string[]>>;

  /** Dispatches host interaction actions (optional) */
  dispatch?: AIComponentPropsDispatch;
}

Data retrieval example:

// Read the dimension field name
const categoryField = encoding.area_row?.[0];

// Read the list of measure field names
const valueFields = encoding.area_column ?? [];

// Read the data rows
const rows = data?.values ?? [];

// Iterate through the data
rows.forEach((row, index) => {
  const category = row[categoryField];   // Dimension value
  const value = row[valueFields[0]];     // Measure value
});

Interaction dispatch

The chart uses dispatch to send interaction events to the host, enabling capabilities such as drill-down, linkage, and jump.

type AIComponentPropsDispatch = (
  param:
    | AIComponentPropsActionSelect
    | AIComponentPropsActionCancelSelect
    | AIComponentPropsActionCancelDrill
    | AIComponentPropsActionCancelLinkage,
) => void;

// Select (triggers drill-down, linkage, or jump)
interface AIComponentPropsActionSelect {
  type: 'select';
  payload: {
    dataIndex: number;  // The index of the selected row in data.values
  };
}

// Cancel selection
interface AIComponentPropsActionCancelSelect {
  type: 'cancelSelect';
}

// Cancel drill-down
interface AIComponentPropsActionCancelDrill {
  type: 'cancelDrill';
}

// Cancel linkage
interface AIComponentPropsActionCancelLinkage {
  type: 'cancelLinkage';

Usage example:

// Trigger drill-down when a chart element is clicked
chart.on('click', (params) => {
  dispatch?.({ type: 'select', payload: { dataIndex: params.dataIndex } });
});

// Cancel selection when a blank area is clicked
chart.getZr().on('click', (e) => {
  if (!e.target) {
    dispatch?.({ type: 'cancelSelect' });
  }
});

List of dispatch actions:

Type

Payload

Resulting effect

select

{ dataIndex: number }

Triggers a data retrieval request to update the chart (drill-down, linkage, or jump).

cancelSelect

None

Cancels the selection and linkage effect.

cancelDrill

None

Cancels the drill-down and returns to the previous level.

cancelLinkage

None

Cancels the linkage and restores its independent display.

Related operations

After the chart is uploaded, you can perform the following operations:

  • In Chart Management, manage the visibility and enabled status of existing charts, or edit or delete charts. For more information, see Manage Custom Charts.

  • Members of your organization can browse and install custom charts published by the enterprise in the Chart Marketplace. For more information, see Chart Marketplace.

  • In My Charts, you can view the charts installed under your account and control whether they are used in AI report generation and editing. For more information, see My Charts.

FAQ

Q: The chart area displays the error "Failed to load external dependency: xxx has no resource URL."

A: Each external_assets entry for a third-party external dependency must have a URL. You can fix this by editing the chart and updating only the external_assets.

Q: The system reports that the build artifact size is too large.

Check if the externals configuration for third-party chart libraries is missing. Large libraries such as ECharts should be declared as external and loaded via CDN.

Q: A certificate error occurs during local debugging.

A: The locally started devServer uses a self-signed HTTPS certificate. Because this certificate is not signed by a Certificate Authority (CA), the browser marks it as insecure. To resolve this, navigate directly to the service URL in your browser (e.g., https://127.0.0.1:{port}), accept the certificate warning, and then refresh the debugging page.

Q: The browser displays the error "127.0.0.1 refused to connect."

A: This indicates that the local custom chart devServer is not running. Run qdt start in the project's root directory to start the service, and then refresh the page.

Q: The preview does not update after I modify the code.

The devServer has hot: false set by default (the output is a UMD external script). After the devServer finishes rebuilding, manually refresh the browser.

Q: I have already uploaded and used a chart. Can I replace its code package? Will the changes apply to existing reports?

A: Yes. When you update a chart's code package, the changes are automatically applied to all existing reports that use it. No manual regeneration is required.