Install
$ agentstack add skill-kensaurus-cursor-kenji-data-visualization ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Data Visualization Skill
Create beautiful, accessible, and interactive data visualizations for dashboards and reports.
CRITICAL: Check Existing First
Before creating ANY visualization, verify:
- Check for existing chart libraries:
cat package.json | grep -i "recharts\|chart\|d3\|visx\|nivo\|tremor"
rg "LineChart|BarChart|PieChart" --type tsx -l | head -10
- Check for existing chart components:
ls -la src/components/charts/ src/components/dashboard/ 2>/dev/null
rg "ResponsiveContainer|Chart" --type tsx | head -10
- Check for design tokens:
cat tailwind.config.* | grep -A10 "chart\|colors"
Why: Use existing chart library and styling conventions.
Recharts (Recommended for React)
Line Chart
'use client'
import {
LineChart,
Line,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
ResponsiveContainer,
Legend,
} from 'recharts'
const data = [
{ month: 'Jan', revenue: 4000, users: 2400 },
{ month: 'Feb', revenue: 3000, users: 1398 },
{ month: 'Mar', revenue: 2000, users: 9800 },
]
export function RevenueChart() {
return (
`$${value}`}
/>
}
cursor={{ stroke: 'hsl(var(--muted))' }}
/>
)
}
function CustomTooltip({ active, payload, label }: any) {
if (!active || !payload) return null
return (
{label}
{payload.map((entry: any, index: number) => (
{entry.name}: {entry.value}
))}
)
}
Bar Chart
'use client'
import { BarChart, Bar, XAxis, YAxis, ResponsiveContainer, Cell } from 'recharts'
const data = [
{ name: 'Mon', value: 12 },
{ name: 'Tue', value: 19 },
{ name: 'Wed', value: 3 },
{ name: 'Thu', value: 5 },
{ name: 'Fri', value: 2 },
]
export function WeeklyChart() {
return (
{data.map((entry, index) => (
))}
)
}
Area Chart with Gradient
'use client'
import { AreaChart, Area, XAxis, YAxis, ResponsiveContainer } from 'recharts'
export function GradientAreaChart({ data }: { data: any[] }) {
return (
)
}
Pie/Donut Chart
'use client'
import { PieChart, Pie, Cell, ResponsiveContainer, Label } from 'recharts'
const COLORS = [
'hsl(var(--primary))',
'hsl(var(--secondary))',
'hsl(var(--accent))',
'hsl(var(--muted))',
]
export function DonutChart({ data, total }: { data: any[]; total: number }) {
return (
{data.map((_, index) => (
))}
)
}
Sparklines (Mini Charts)
'use client'
import { LineChart, Line, ResponsiveContainer } from 'recharts'
interface SparklineProps {
data: number[]
color?: string
height?: number
}
export function Sparkline({ data, color = 'hsl(var(--primary))', height = 40 }: SparklineProps) {
const chartData = data.map((value, index) => ({ index, value }))
return (
)
}
// Usage in stats card
Revenue
$45,231
Stat Cards with Trends
import { ArrowUpIcon, ArrowDownIcon } from 'lucide-react'
import { cn } from '@/lib/utils'
interface StatCardProps {
title: string
value: string
change: number
trend: 'up' | 'down'
sparklineData?: number[]
}
export function StatCard({ title, value, change, trend, sparklineData }: StatCardProps) {
return (
{title}
{value}
{trend === 'up' ? (
) : (
)}
{Math.abs(change)}%
{sparklineData && (
)}
)
}
Real-time Data Updates
'use client'
import { useEffect, useState } from 'react'
import { LineChart, Line, ResponsiveContainer, YAxis } from 'recharts'
export function RealtimeChart() {
const [data, setData] = useState([])
useEffect(() => {
const interval = setInterval(() => {
setData((prev) => {
const newPoint = {
time: Date.now(),
value: Math.random() * 100,
}
// Keep last 20 points
const updated = [...prev, newPoint].slice(-20)
return updated
})
}, 1000)
return () => clearInterval(interval)
}, [])
return (
)
}
D3.js for Custom Visualizations
'use client'
import { useEffect, useRef } from 'react'
import * as d3 from 'd3'
export function CustomD3Chart({ data }: { data: { label: string; value: number }[] }) {
const svgRef = useRef(null)
useEffect(() => {
if (!svgRef.current || !data.length) return
const svg = d3.select(svgRef.current)
const width = svgRef.current.clientWidth
const height = svgRef.current.clientHeight
const margin = { top: 20, right: 20, bottom: 30, left: 40 }
svg.selectAll('*').remove()
const x = d3
.scaleBand()
.domain(data.map((d) => d.label))
.range([margin.left, width - margin.right])
.padding(0.1)
const y = d3
.scaleLinear()
.domain([0, d3.max(data, (d) => d.value) || 0])
.nice()
.range([height - margin.bottom, margin.top])
// Bars
svg
.selectAll('rect')
.data(data)
.join('rect')
.attr('x', (d) => x(d.label) || 0)
.attr('y', height - margin.bottom)
.attr('width', x.bandwidth())
.attr('height', 0)
.attr('fill', 'hsl(var(--primary))')
.attr('rx', 4)
.transition()
.duration(750)
.attr('y', (d) => y(d.value))
.attr('height', (d) => y(0) - y(d.value))
// X Axis
svg
.append('g')
.attr('transform', `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x).tickSize(0))
.selectAll('text')
.attr('class', 'fill-muted-foreground text-xs')
}, [data])
return
}
Accessibility
// Always include ARIA labels and descriptions
{/* Chart content */}
{/* Screen reader alternative */}
Monthly Revenue Data
MonthRevenue
{data.map((d) => (
{d.month}
${d.revenue}
))}
Validation
After creating visualizations:
- Responsive → Charts resize properly on all screens
- Accessible → Screen reader alternatives provided
- Performance → Large datasets use virtualization/sampling
- Loading states → Skeleton shown while data loads
- Empty states → Meaningful message when no data
- Color contrast → Meets WCAG guidelines
- Tooltips → Provide detailed data on hover
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: kensaurus
- Source: kensaurus/cursor-kenji
- License: MIT
- Homepage: https://github.com/kensaurus/cursor-kenji
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.