From geepers-mcp
Comprehensive data visualization toolkit for creating beautiful, mathematically elegant visualizations with D3.js, Chart.js, and custom SVG. Use when (1) building interactive data visualizations, (2) designing color palettes for charts, (3) choosing scales and visual encodings, (4) creating data pipelines from Census/SEC/Wikipedia APIs, (5) crafting narrative-driven data stories, (6) making perceptually accurate charts, or (7) implementing force-directed networks, timelines, or geographic maps.
npx claudepluginhub lukeslp/geepers-mcp --plugin geepers-mcpThis skill uses the workspace's default tool permissions.
Create beautiful, mathematically elegant, emotionally resonant data visualizations.
Guides data visualization with perceptual encoding rules, chart selection, layout algorithms, interaction patterns, and libraries like D3, Recharts, Victory.
Guides creation of custom interactive D3.js visualizations—bar/line/scatter charts, networks, maps, hierarchies—with zoom/pan/brush interactions and animations. Use for low-level SVG/DOM control beyond Chart.js/Highcharts.
Guides building interactive D3.js data visualizations with custom layouts, scales, axes, transitions for networks, geo maps in vanilla JS, React, Vue, Svelte.
Share bugs, ideas, or general feedback.
Create beautiful, mathematically elegant, emotionally resonant data visualizations.
Every visualization should:
Scale Selection:
| Scale | Use When | Example |
|---|---|---|
| Linear | Evenly distributed data | Temperature |
| Log | Multiple orders of magnitude | Population (100 to 1B) |
| Sqrt | Encoding area (circles) | Bubble chart radius |
| Time | Temporal data | Dates |
Perceptual Honesty - Area scales with square of radius, so use sqrt:
// WRONG: Linear radius exaggerates large values
const badScale = d3.scaleLinear().domain([0, max]).range([0, maxRadius]);
// RIGHT: Sqrt maintains perceptual accuracy
const goodScale = d3.scaleSqrt().domain([0, max]).range([0, maxRadius]);
Palette Types:
Colorblind-Safe Palette (8 colors):
const colorblindSafe = [
'#332288', '#117733', '#44AA99', '#88CCEE',
'#DDCC77', '#CC6677', '#AA4499', '#882255'
];
Always use redundant encoding - don't rely on color alone:
node.attr('fill', d => colorScale(d.category))
.attr('d', d => symbolScale(d.category)); // Shape too!
Force Simulation:
const simulation = d3.forceSimulation(nodes)
.force('charge', d3.forceManyBody().strength(-300))
.force('link', d3.forceLink(links).id(d => d.id))
.force('center', d3.forceCenter(width/2, height/2))
.force('collision', d3.forceCollide().radius(d => d.r + 2));
Responsive SVG:
const svg = d3.select('#chart')
.append('svg')
.attr('viewBox', `0 0 ${width} ${height}`)
.attr('preserveAspectRatio', 'xMidYMid meet');
Touch-Friendly (44x44px minimum):
node.append('circle')
.attr('class', 'hit-area')
.attr('r', Math.max(actualRadius, 22))
.attr('fill', 'transparent');
Three Acts:
Progressive Disclosure:
Level 1: Overview → Level 2: Exploration → Level 3: Detail → Level 4: Context
Structure:
scripts/
├── 01_fetch_raw.py # API calls with caching
├── 02_clean_data.py # Transformation
├── 03_validate.py # Quality checks
└── 04_export.py # Final format
Source Documentation (every dataset needs):
Start a new visualization project with boilerplate code.
# Available templates: force-network, timeline, choropleth, radial-tree, sankey, bubble-chart, treemap
python3 scripts/d3-scaffold.py my-viz --type radial-tree
Instantly create an HTML file from a data file.
# From JSON
python3 scripts/viz-generator.py data.json --template sankey
# From CSV
python3 scripts/viz-generator.py data.csv --template bar-race
dream_visualize_dataGenerates a collaborative visualization artifact.
Parameters:
data (string/json): Data to visualize.template (string): One of [force-network, timeline, choropleth, radial-tree, sankey, bubble-chart, treemap].title (string): Title for the chart.dream_list_viz_templatesReturns descriptions of all available visualization templates.
python3 scripts/color-palette.py --type sequential --hue blue --steps 9
python3 scripts/analyze-distribution.py data.csv --column value