Skip to main content

Pivot Charts Tutorial

This guide shows you how to turn your pivot table data into charts using @mindfiredigital/pivothead-analytics. By the end you will have a working chart in your project.


Step 1 — Install the package

npm install @mindfiredigital/pivothead-analytics

What happens after install

The package runs a postinstall setup prompt automatically in your terminal:

  ┌──────────────────────────────────────────────────────┐
│ @mindfiredigital/pivothead-analytics Setup │
└──────────────────────────────────────────────────────┘

Which charting library would you like to install?

[1] Chart.js Lightweight, easy to use, browser-first charting
[2] Apache ECharts Feature-rich, interactive charts for complex data
[3] Plotly.js Scientific & statistical charts, great for data science
[4] D3.js Maximum flexibility with custom SVG-based rendering

Enter number(s) separated by commas (e.g. 1 or 1,3),
or press Enter to skip and install manually later.

>

Type a number and press Enter. The script:

  • Detects your package manager (npm / pnpm / yarn / bun) automatically
  • Installs the chosen library for you — no separate install command needed
  • Writes .pivothead-analytics.json to your project root so ChartEngine knows which library to use at runtime
  • Handles monorepo workspace roots automatically (adds -w / -W flag when needed)

You only need one library. Chart.js is the best starting point.

#LibraryBest for
1Chart.js (recommended)Standard charts, lightweight apps
2Apache EChartsFeature-rich interactive dashboards
3PlotlyScientific / statistical / 3D charts
4D3Fully custom SVG-based charts

CI / non-interactive environments

In CI pipelines or any environment without an interactive terminal, the prompt is skipped automatically. Install your chosen library manually and set the PIVOTHEAD_LIBRARY environment variable so ChartEngine can detect it at runtime:

# Install the library
npm install chart.js

# Tell ChartEngine which one to use (add to your .env or CI environment)
PIVOTHEAD_LIBRARY=chartjs

Valid values: chartjs · echarts · plotly · d3

To suppress the prompt entirely in any environment:

PIVOTHEAD_SKIP_SETUP=true npm install @mindfiredigital/pivothead-analytics

Monorepo projects

If you are in a pnpm / yarn / npm workspaces monorepo, the postinstall detects it and passes the correct workspace flag (-w / -W) when installing the charting library. No extra configuration needed.

If you install from a workspace package rather than the root, run the install from that package's directory or target it explicitly:

# pnpm
pnpm add @mindfiredigital/pivothead-analytics chart.js --filter my-app

# yarn
yarn workspace my-app add @mindfiredigital/pivothead-analytics chart.js

The .pivothead-analytics.json file

After a successful interactive install, a config file is written to your project root:

{
"library": "chartjs",
"installedLibraries": ["chartjs"],
"generatedAt": "2025-01-01T00:00:00.000Z"
}

ChartEngine reads this file at startup to auto-detect which renderer to use. You can:

  • Commit it — keeps the choice in version control so teammates don't need to re-run setup
  • Gitignore it — teammates will be prompted on their first install instead

If you skipped the prompt and installed manually, create this file yourself or rely on the PIVOTHEAD_LIBRARY env var instead.


Step 2 — Prepare your data and PivotEngine

ChartEngine reads data from a PivotEngine. Set yours up first:

import { PivotEngine } from '@mindfiredigital/pivothead';

const data = [
{ region: 'North', product: 'Laptops', revenue: 45000 },
{ region: 'North', product: 'Phones', revenue: 32000 },
{ region: 'South', product: 'Laptops', revenue: 38000 },
{ region: 'South', product: 'Phones', revenue: 41000 },
{ region: 'East', product: 'Laptops', revenue: 52000 },
{ region: 'East', product: 'Phones', revenue: 28000 },
];

const config = {
rows: [{ uniqueName: 'region', caption: 'Region' }],
columns: [{ uniqueName: 'product', caption: 'Product' }],
measures: [{ uniqueName: 'revenue', caption: 'Revenue', aggregation: 'sum' }],
};

const engine = new PivotEngine(data, config);

Step 3 — Add a container element

Add a <div> where the chart will be drawn. Give it a fixed size.

<div id="myChart" style="width: 600px; height: 400px;"></div>

Step 4 — Create ChartEngine and render

Import your charting library and pass it directly to ChartEngine. This is required in any bundler-based project (Vite, webpack, etc.) because bundlers use ES modules — require() is not available at runtime.

import { Chart, registerables } from 'chart.js';
import { ChartEngine } from '@mindfiredigital/pivothead-analytics';

// Required: register all Chart.js components
Chart.register(...registerables);

// Pass the Chart object in — this is the key step
const chartEngine = new ChartEngine(engine, { chartInstance: Chart });

// Render a column chart
chartEngine.column({
container: '#myChart',
style: { title: 'Revenue by Region' },
});

That's it — your chart is on screen.


Step 5 — Pick a specific chart type

Replace column with any of these convenience methods:

chartEngine.column({ container: '#chart' });       // vertical bars
chartEngine.bar({ container: '#chart' }); // horizontal bars
chartEngine.line({ container: '#chart' }); // line chart
chartEngine.area({ container: '#chart' }); // area chart
chartEngine.pie({ container: '#chart' }); // pie chart
chartEngine.doughnut({ container: '#chart' }); // doughnut chart
chartEngine.scatter({ container: '#chart' }); // scatter plot
chartEngine.heatmap({ container: '#chart' }); // heatmap grid
chartEngine.stackedColumn({ container: '#chart' }); // stacked columns
chartEngine.stackedBar({ container: '#chart' }); // stacked bars
chartEngine.histogram({ container: '#chart' }); // frequency histogram
chartEngine.funnel({ container: '#chart' }); // funnel stages
chartEngine.combo({ container: '#chart' }); // bar + line combo

Let the engine pick the best chart automatically

Not sure which chart fits your data? Use auto():

chartEngine.auto({
container: '#myChart',
style: { title: 'Auto-selected Chart' },
});

The engine checks your data structure (dimensions, measures, cardinality) and picks the most suitable chart type.

To see the recommendations before rendering:

const recommendations = chartEngine.recommend();

// Each recommendation has: type, score (0–1), reason
recommendations.forEach(rec => {
console.log(`${rec.type}: ${Math.round(rec.score * 100)}% — ${rec.reason}`);
});

// Render the top recommendation
chartEngine.renderRecommendation(recommendations[0], '#myChart');

Styling your chart

Pass a style object to any render call:

chartEngine.column({
container: '#myChart',
style: {
title: 'Revenue by Region',
subtitle: 'Q1 2025',
showLegend: true,
legendPosition: 'bottom', // 'top' | 'bottom' | 'left' | 'right'
showGrid: true,
animated: true,
colorScheme: 'vibrant', // see colour palette list below
},
});

Available colour palettes

tableau10 (default) · colorBlind · categorical · pastel · vibrant · sequentialBlues · sequentialGreens · sequentialReds · sequentialOranges · sequentialPurples · divergingRedBlue · divergingRedGreen · divergingPurpleGreen

Use colorBlind when accessibility matters.

Custom colours

chartEngine.column({
container: '#myChart',
style: {
colors: ['#6366f1', '#ec4899', '#22c55e', '#fb923c'],
},
});

Format values

Display numbers as currency, percentages, or compact notation:

chartEngine.column({
container: '#myChart',
format: {
valueFormat: 'currency', // 'number' | 'currency' | 'percent' | 'compact'
currency: 'USD',
locale: 'en-US',
decimals: 0,
},
});

Filter what the chart shows

const chartService = chartEngine.getChartService();

// Show only specific rows, limit to top 5
chartService.setFilters({
selectedMeasure: 'revenue',
selectedRows: ['North', 'South'],
limit: 5,
});

// Refresh the chart to reflect the new filters
chartEngine.updateAllCharts();

// Get available options (useful for building filter dropdowns)
const options = chartService.getAvailableFilterOptions();
// options.measures → [{ uniqueName: 'revenue', caption: 'Revenue' }]
// options.rows → ['North', 'South', 'East']
// options.columns → ['Laptops', 'Phones']

// Remove all filters
chartService.resetFilters();

Switching chart types on the fly

Destroy the old chart, then render a new one in the same container:

function switchChart(newType) {
chartEngine.destroyChart('#myChart');
chartEngine.render({
container: '#myChart',
type: newType,
style: { title: 'Sales Overview', animated: true },
});
}

document.getElementById('chartType').addEventListener('change', e => {
switchChart(e.target.value);
});

Exporting charts

// Download as image or document
await chartEngine.exportAsPng('#myChart', 'sales-report');
await chartEngine.exportAsSvg('#myChart', 'sales-vector');
await chartEngine.exportAsPdf('#myChart', 'sales-document');

// Download the underlying data
await chartEngine.exportAsCsv('#myChart', 'chart-data');
await chartEngine.exportAsJson('#myChart', 'chart-data');

// Get a Blob to upload or email
const blob = await chartEngine.getChartBlob('#myChart', 'png');

Using a different rendering library

Import your chosen library and pass it as the matching instance option:

// ECharts
import * as echarts from 'echarts';
const chartEngine = new ChartEngine(engine, { echartsInstance: echarts });

// Plotly
import Plotly from 'plotly.js-dist';
const chartEngine = new ChartEngine(engine, { plotlyInstance: Plotly });

// D3
import * as d3 from 'd3';
const chartEngine = new ChartEngine(engine, { d3Instance: d3 });

Cleanup

Always dispose the engine when you are done (e.g., on page navigation):

chartEngine.dispose();

This destroys all active charts and unsubscribes from PivotEngine updates.


Complete working example

import { Chart, registerables } from 'chart.js';
import { PivotEngine } from '@mindfiredigital/pivothead';
import { ChartEngine } from '@mindfiredigital/pivothead-analytics';

// 1. Register Chart.js components
Chart.register(...registerables);

// 2. Data + pivot config
const data = [
{ region: 'North', product: 'Laptops', revenue: 45000 },
{ region: 'South', product: 'Laptops', revenue: 38000 },
{ region: 'East', product: 'Phones', revenue: 28000 },
];

const engine = new PivotEngine(data, {
rows: [{ uniqueName: 'region', caption: 'Region' }],
columns: [{ uniqueName: 'product', caption: 'Product' }],
measures: [{ uniqueName: 'revenue', caption: 'Revenue', aggregation: 'sum' }],
});

// 3. Chart engine — pass chartInstance so it works in any bundler (Vite, webpack, etc.)
const chartEngine = new ChartEngine(engine, {
chartInstance: Chart,
defaultStyle: { colorScheme: 'tableau10', animated: true, showLegend: true },
defaultFormat: { valueFormat: 'currency', currency: 'USD' },
});

// 3. Get recommendations and render the best one
const best = chartEngine.getBestRecommendation();
console.log('Rendering:', best.type, '—', best.reason);
chartEngine.renderRecommendation(best, '#mainChart');

// 4. Export on button click
document.getElementById('exportBtn').addEventListener('click', async () => {
await chartEngine.exportAsPng('#mainChart', 'dashboard');
});

// 5. Cleanup
window.addEventListener('beforeunload', () => {
chartEngine.dispose();
});

Next steps