<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ data visualization tools - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ data visualization tools - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Thu, 22 Oct 2026 23:32:09 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/data-visualization-tools/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Add shadcn Charts to a Next.js App Without Writing Recharts Boilerplate ]]>
                </title>
                <description>
                    <![CDATA[ Charts look like a small task on a ticket. Then you open the Recharts docs and remember how much setup every chart needs: a config object for labels and colors, axes, a tooltip, a legend, colors that  ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-add-shadcn-ui-charts-to-nextjs/</link>
                <guid isPermaLink="false">6abf4b9d63317980cdaece08</guid>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ shadcn ]]>
                    </category>
                
                    <category>
                        <![CDATA[ charts ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data visualization tools ]]>
                    </category>
                
                    <category>
                        <![CDATA[ TypeScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ash ]]>
                </dc:creator>
                <pubDate>Fri, 02 Oct 2026 06:13:49 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/a6e5c1d7-5d61-4cc0-94d8-3a3e068d97e4.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Charts look like a small task on a ticket. Then you open the Recharts docs and remember how much setup every chart needs: a config object for labels and colors, axes, a tooltip, a legend, colors that work in dark mode, and a container that resizes properly. Most of us copy all of that from the last project and rename the keys.</p>
<p>The shadcn/ui chart component removes part of this work. It wraps Recharts with theme-aware colors and tooltips. But you still write every chart by hand.</p>
<p>So I built ChartCN, a free and open-source <a href="https://www.shadcndeck.com/chartcn">shadcn chart generator</a>. You paste your data, pick a chart, and copy one TSX file that depends only on the shadcn/ui chart component and Recharts. It's MIT licensed, and there's no account or extra package.</p>
<p>In this tutorial, you'll learn how to add a revenue-versus-expenses bar chart to a fresh Next.js app. We'll walk through what each part of the generated code does, and then connect the chart to data loaded in a Server Component. The tool saves you the typing, but Steps 5 and 6 apply to any shadcn/ui chart, whether you generate it or write it yourself.</p>
<p><strong>Prerequisites:</strong> You should be comfortable with React and have Node.js installed. Basic familiarity with the Next.js App Router helps, but every step is explained.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a href="#heading-what-youll-build">What You'll Build</a></p>
</li>
<li><p><a href="#heading-step-1-create-a-nextjs-app-and-initialize-shadcnui">Step 1: Create a Next.js App and Initialize shadcn/ui</a></p>
</li>
<li><p><a href="#heading-step-2-add-the-shadcnui-chart-component">Step 2: Add the shadcn/ui Chart Component</a></p>
</li>
<li><p><a href="#heading-step-3-generate-the-chart-component-in-chartcn">Step 3: Generate the Chart Component in ChartCN</a></p>
</li>
<li><p><a href="#heading-step-4-add-the-chart-to-your-page">Step 4: Add the Chart to Your Page</a></p>
</li>
<li><p><a href="#heading-step-5-understand-the-generated-code">Step 5: Understand the Generated Code</a></p>
</li>
<li><p><a href="#heading-step-6-pass-live-data-as-a-prop">Step 6: Pass Live Data as a Prop</a></p>
</li>
<li><p><a href="#heading-common-issues-and-how-to-fix-them">Common Issues and How to Fix Them</a></p>
</li>
<li><p><a href="#heading-summary">Summary</a></p>
</li>
</ul>
<h2 id="heading-what-youll-build">What You'll Build</h2>
<p>By the end, you'll have two pages:</p>
<ul>
<li><p><code>/</code> shows a grouped bar chart with the data written directly in the component. This is the fastest way to get a chart on screen.</p>
</li>
<li><p><code>/live</code> shows the same chart, but the data comes from an async function running on the server. This is the version you'd use with a real database or API.</p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/6a4ea012258c41204fefcf8b/546e7105-3d43-4bd0-a064-a877fffe930a.png" alt="Shadcn Charts - Finished Bar Chart" style="display: block;" width="667" height="661" loading="lazy">

<p>The chart has gradient bars, compact axis labels (40K instead of 40000), a legend, and a tooltip that shows the month's total and each series' share of it.</p>
<h2 id="heading-step-1-create-a-nextjs-app-and-initialize-shadcnui">Step 1: Create a Next.js App and Initialize shadcn/ui</h2>
<p>Create a new app and move into it:</p>
<pre><code class="language-bash">npx create-next-app@latest my-charts-app
cd my-charts-app
</code></pre>
<p>Accept the recommended defaults. You need TypeScript, Tailwind CSS, and the App Router.</p>
<p>Next, initialize shadcn/ui:</p>
<pre><code class="language-bash">npx shadcn@latest init
</code></pre>
<p>This command does three things you'll rely on later:</p>
<ol>
<li><p>It creates <code>components.json</code>, which tells the shadcn/ui CLI where to put components.</p>
</li>
<li><p>It adds <code>lib/utils.ts</code> with the <code>cn()</code> class-merging helper.</p>
</li>
<li><p>It writes theme variables into <code>app/globals.css</code>, including five chart colors: <code>--chart-1</code> through <code>--chart-5</code>, with separate values for light and dark mode.</p>
</li>
</ol>
<p>Those five chart variables matter. Every generated chart uses them, so changing a chart color across your whole app means editing one line of CSS.</p>
<h2 id="heading-step-2-add-the-shadcnui-chart-component">Step 2: Add the shadcn/ui Chart Component</h2>
<p>Now add the chart component:</p>
<pre><code class="language-bash">npx shadcn@latest add chart
</code></pre>
<p>This installs <code>recharts</code> and creates <code>components/ui/chart.tsx</code>. That file exports the building blocks you'll see in the generated code:</p>
<ul>
<li><p><code>ChartContainer</code> wraps Recharts' <code>ResponsiveContainer</code>, so the chart fills its parent.</p>
</li>
<li><p><code>ChartConfig</code> is the type for the object that maps each data key to a label and a color.</p>
</li>
<li><p><code>ChartTooltip</code>, <code>ChartTooltipContent</code>, <code>ChartLegend</code>, and <code>ChartLegendContent</code> are styled versions of the Recharts tooltip and legend.</p>
</li>
</ul>
<p>Before moving on, check which Recharts version was installed:</p>
<pre><code class="language-bash">npm ls recharts
</code></pre>
<p>The code ChartCN generates targets <strong>Recharts 3</strong>. If you see a 2.x version, upgrade it:</p>
<pre><code class="language-bash">npm install recharts@latest
</code></pre>
<p><strong>Takeaway:</strong> the shadcn/ui chart component is a thin layer over Recharts. It doesn't replace Recharts. It gives Recharts your theme.</p>
<h2 id="heading-step-3-generate-the-chart-component-in-chartcn">Step 3: Generate the Chart Component in ChartCN</h2>
<p>Open the <a href="https://www.shadcndeck.com/chartcn/charts/bar">ChartCN bar chart page</a>. The data panel has three tabs: <strong>Paste data</strong>, <strong>Upload file</strong>, and <strong>Edit table</strong>. Paste this CSV into the <strong>Paste data</strong> tab:</p>
<pre><code class="language-plaintext">Month,Revenue,Expenses
Jan,42000,31000
Feb,58000,34000
Mar,51000,29000
Apr,67000,38000
May,72000,41000
Jun,69000,37000
</code></pre>
<p>ChartCN treats the first column as the category axis (the x-axis for a bar chart) and every other column as a numeric series. JSON, TSV, and Markdown tables also work, and the format is detected automatically.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6a4ea012258c41204fefcf8b/997a85da-f44d-4e88-8ffe-120ea66b8884.png" alt="Shadcn Charts - Bar Chart" style="display: block;" width="671" height="659" loading="lazy">

<p>Above the preview, set these options:</p>
<ul>
<li><p><strong>Layout:</strong> Grouped</p>
</li>
<li><p><strong>Tooltip:</strong> Breakdown</p>
</li>
<li><p><strong>Code:</strong> Inline data</p>
</li>
</ul>
<p>Then click <strong>Copy component</strong> in the <code>chart.tsx</code> panel below the preview.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6a4ea012258c41204fefcf8b/3317c6c9-e4f4-4b59-ad19-2076728048cd.png" alt="Shadcn Charts - ChartCn Copy component" style="display: block;" width="656" height="569" loading="lazy">

<h2 id="heading-step-4-add-the-chart-to-your-page">Step 4: Add the Chart to Your Page</h2>
<p>Create a new file at <code>components/revenue-chart.tsx</code> and paste the copied code into it.</p>
<p>Don't save it as <code>components/ui/chart.tsx</code>. ChartCN labels its output <code>chart.tsx</code>, but that path already holds the <a href="https://www.shadcndeck.com/blog/shadcn-components">shadcn component</a> from Step 2, and overwriting it breaks every chart in your app.</p>
<p>The generated component is always exported as <code>Chart</code>, so give it a clearer name when you import it. Replace <code>app/page.tsx</code> with this:</p>
<pre><code class="language-tsx">// app/page.tsx
import { Chart as RevenueChart } from "@/components/revenue-chart"

export default function Home() {
  return (
    &lt;main className="mx-auto max-w-3xl p-8"&gt;
      &lt;h1 className="mb-6 text-2xl font-semibold"&gt;Revenue vs. expenses&lt;/h1&gt;
      &lt;RevenueChart /&gt;
    &lt;/main&gt;
  )
}
</code></pre>
<p>Run <code>npm run dev</code> and open <code>http://localhost:3000</code>. You should see the chart.</p>
<p><strong>Takeaway:</strong> a generated chart is just a component in your project. There's nothing to configure and no package to keep in sync.</p>
<h2 id="heading-step-5-understand-the-generated-code">Step 5: Understand the Generated Code</h2>
<p>You own this file now, so it's worth knowing what each part does. Here are the important pieces, trimmed for length.</p>
<p>The file starts with a directive and its imports:</p>
<pre><code class="language-tsx">// components/revenue-chart.tsx
"use client"

import { useId } from "react"
import { Bar, BarChart, CartesianGrid, Rectangle, XAxis, YAxis } from "recharts"
import {
  type ChartConfig,
  ChartContainer,
  ChartLegend,
  ChartLegendContent,
  ChartTooltip,
} from "@/components/ui/chart"
</code></pre>
<p>Recharts measures the DOM and handles mouse events, so the chart must be a Client Component. <code>app/page.tsx</code> can stay a Server Component because it only renders the chart.</p>
<p>Next come the data and the config:</p>
<pre><code class="language-tsx">const data = [
  { Month: "Jan", Revenue: 42000, Expenses: 31000 },
  { Month: "Feb", Revenue: 58000, Expenses: 34000 },
  // ...
]

const chartConfig = {
  Revenue: { label: "Revenue", color: "var(--chart-1)" },
  Expenses: { label: "Expenses", color: "var(--chart-2)" },
} satisfies ChartConfig
</code></pre>
<p>The keys in <code>chartConfig</code> must match the keys in your data. <code>ChartContainer</code> reads this config and creates a CSS variable for each key, scoped to this chart: <code>--color-Revenue</code> and <code>--color-Expenses</code>. Each one points at a theme color, so the chart switches colors in dark mode on its own.</p>
<p>The chart itself uses those variables:</p>
<pre><code class="language-tsx">&lt;ChartContainer config={chartConfig} className="aspect-auto h-[350px] w-full"&gt;
  &lt;BarChart accessibilityLayer data={data} barCategoryGap="30%" barGap={4}&gt;
    {/* ...gradient &lt;defs&gt;, grid, axes, tooltip, legend... */}
    &lt;Bar
      dataKey="Revenue"
      fill="var(--color-Revenue)"
      shape={(props) =&gt; &lt;Rectangle {...props} fill={`url(#${uid}-fill-0)`} /&gt;}
      radius={[6, 6, 0, 0]}
      maxBarSize={36}
    /&gt;
  &lt;/BarChart&gt;
&lt;/ChartContainer&gt;
</code></pre>
<p>A few details are worth knowing:</p>
<ul>
<li><p><strong>Height</strong> is set by <code>h-[350px]</code> on <code>ChartContainer</code>. Change it there.</p>
</li>
<li><p><strong>The gradient</strong> is drawn by the <code>shape</code> prop, while <code>fill</code> stays a solid color. That's why the legend and tooltip dots show a clean color instead of a gradient.</p>
</li>
<li><p><code>uid</code> comes from <code>useId()</code>, so the gradient IDs stay unique if you render two charts on the same page.</p>
</li>
</ul>
<p>The file also includes a <code>ChartBreakdownTooltip</code> component, about 70 lines, that shows the total and each series' percentage. If you'd rather use the standard <a href="https://www.shadcndeck.com/blog/shadcn-tooltip-component">shadcn tooltip</a>, pick <strong>Tooltip: Simple</strong> in ChartCN before copying. The whole file then drops from about 120 lines to about 50.</p>
<p><strong>Takeaway:</strong> in shadcn/ui charts, colors flow from theme variables through <code>chartConfig</code> into <code>--color-&lt;key&gt;</code> variables. Once you understand that path, you can edit any chart by hand.</p>
<h2 id="heading-step-6-pass-live-data-as-a-prop">Step 6: Pass Live Data as a Prop</h2>
<p>Hardcoded data is fine for a demo. For real data, go back to ChartCN, switch <strong>Code</strong> to <strong>Data as prop</strong>, and copy again. Save this version as <code>components/revenue-chart-live.tsx</code>.</p>
<p>The chart markup is identical. Only the top of the file changes: the <code>data</code> array is replaced by a type, and the component accepts <code>data</code> as a prop:</p>
<pre><code class="language-tsx">// components/revenue-chart-live.tsx
export type ChartRow = { Month: string; Revenue: number | null; Expenses: number | null }

export interface ChartProps {
  data: ChartRow[]
}

// ...chartConfig is unchanged...

export function Chart({ data }: ChartProps) {
  // ...same JSX as before
}
</code></pre>
<p>The series are typed as <code>number | null</code> because real data has gaps. A <code>null</code> value renders as a missing bar, not as a bar of zero.</p>
<p>Now create a function that loads the data on the server:</p>
<pre><code class="language-ts">// lib/get-revenue.ts
import type { ChartRow } from "@/components/revenue-chart-live"

export async function getRevenue(): Promise&lt;ChartRow[]&gt; {
  // Replace this with your database query or API call.
  // For example: const res = await fetch("https://api.example.com/revenue")
  return [
    { Month: "Jan", Revenue: 42000, Expenses: 31000 },
    { Month: "Feb", Revenue: 58000, Expenses: 34000 },
    { Month: "Mar", Revenue: 51000, Expenses: 29000 },
    { Month: "Apr", Revenue: 67000, Expenses: 38000 },
    { Month: "May", Revenue: 72000, Expenses: null },
  ]
}
</code></pre>
<p>Then call it from a Server Component page:</p>
<pre><code class="language-tsx">// app/live/page.tsx
import { Chart as RevenueChart } from "@/components/revenue-chart-live"
import { getRevenue } from "@/lib/get-revenue"

export default async function LivePage() {
  const data = await getRevenue()

  return (
    &lt;main className="mx-auto max-w-3xl p-8"&gt;
      &lt;h1 className="mb-6 text-2xl font-semibold"&gt;Revenue vs. expenses&lt;/h1&gt;
      &lt;RevenueChart data={data} /&gt;
    &lt;/main&gt;
  )
}
</code></pre>
<p>Open <code>http://localhost:3000/live</code>. May shows a Revenue bar with no Expenses bar next to it, because that value is <code>null</code>.</p>
<p>The page fetches on the server and sends only the rows to the client component. Your database credentials and API keys stay on the server. When you swap in a real <code>fetch</code> or database call, check the <a href="https://nextjs.org/docs/app/getting-started/fetching-data">Next.js data fetching docs</a> to control how often the data refreshes.</p>
<p><strong>Takeaway:</strong> keep data loading in a Server Component and rendering in a Client Component. The exported <code>ChartRow</code> type makes TypeScript check that your data matches what the chart expects.</p>
<h2 id="heading-common-issues-and-how-to-fix-them">Common Issues and How to Fix Them</h2>
<p><strong>Type errors such as "Property 'itemSorter' does not exist".</strong> Your project has Recharts 2 installed. Run <code>npm install recharts@latest</code> to upgrade to Recharts 3.</p>
<p><strong>The bars are black and the legend dots are missing.</strong> Your <code>app/globals.css</code> doesn't define <code>--chart-1</code> through <code>--chart-5</code>. Run <code>npx shadcn@latest init</code> again, or copy the chart variables from the shadcn/ui theming docs.</p>
<p><strong>Every chart stopped working after you pasted one.</strong> You probably saved the generated file over <code>components/ui/chart.tsx</code>. Restore it with <code>npx shadcn@latest add chart --overwrite</code> and save your chart under a different name.</p>
<p><strong>Two charts on one page have the same name.</strong> Every generated component is exported as <code>Chart</code>. Rename it when you import it, for example <code>import { Chart as SignupsChart } from "@/components/signups-chart"</code>.</p>
<h2 id="heading-summary">Summary</h2>
<ol>
<li><p><strong>The shadcn/ui chart component themes Recharts.</strong> It doesn't replace it, and ChartCN's output requires Recharts 3.</p>
</li>
<li><p><strong>Colors flow from CSS variables.</strong> <code>--chart-1</code> becomes <code>--color-Revenue</code> through <code>chartConfig</code>, so dark mode works without extra code.</p>
</li>
<li><p><strong>Save generated charts under their own names.</strong> <code>components/ui/chart.tsx</code> belongs to shadcn/ui.</p>
</li>
<li><p><strong>Use Data as prop for real data.</strong> Load it in a Server Component and pass the typed rows to the chart.</p>
</li>
<li><p><code>null</code> <strong>means "no data".</strong> Gaps render as gaps, not as zeros.</p>
</li>
</ol>
<p>Because ChartCN is a <a href="https://www.shadcndeck.com/chartcn">shadcn chart generator</a> rather than a component library, there is no ChartCN package to install or keep updated. You can browse all 13 <a href="https://www.shadcndeck.com/chartcn/charts">shadcn charts</a> it supports, including line, area, pie, radar, KPI cards, waterfall, and a heatmap. They all follow the same paste, pick, and copy workflow you used here.</p>
<p>The source is on <a href="https://github.com/ShadcnDeck/chartcn-shadcn-chart-generator">GitHub</a> under the MIT license. If it's useful, a star helps other developers find it.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
