# Next.js Candlestick Chart

A Next.js candlestick chart for the App Router: OHLC prices in an ApexCharts client component of AdminKit PRO, the chart of the crypto dashboard.

> This component is only available in **AdminKit PRO**. [Learn more](/pricing/#nextjs).

Use a candlestick chart for prices that move. One candle stands for one period and shows where the price opened, how high and low it went, and where it closed: open, high, low and close, or OHLC for short. In [AdminKit for Next.js](/nextjs/), `ApexChart` draws it with [ApexCharts](https://apexcharts.com/), as on the crypto dashboard. See [Chart setup](/nextjs/docs/charts/overview/#apexcharts) for the component.

`ApexChart` draws in the browser, so it is a client component. Your page is a server component, which renders on the server and cannot pass the options function to it. Write the chart as a client component file, with the data and the options function, and render it from the page.

## Example

```html
<div id="apexcharts-candlestick"></div>

<script>
var seriesData = [
  { x: new Date(2025, 1, 1), y: [51.98, 56.29, 51.59, 53.85] },
  { x: new Date(2025, 2, 1), y: [53.66, 54.99, 51.35, 52.95] },
  { x: new Date(2025, 3, 1), y: [52.96, 53.78, 51.54, 52.48] },
  { x: new Date(2025, 4, 1), y: [52.54, 52.79, 47.88, 49.24] },
  { x: new Date(2025, 5, 1), y: [49.10, 52.86, 47.70, 52.78] },
  { x: new Date(2025, 6, 1), y: [52.83, 53.48, 50.32, 52.29] },
  { x: new Date(2025, 7, 1), y: [52.20, 54.48, 51.64, 52.58] },
  { x: new Date(2025, 8, 1), y: [52.76, 57.35, 52.15, 57.03] },
  { x: new Date(2025, 9, 1), y: [57.04, 58.15, 48.88, 56.19] },
  { x: new Date(2025, 10, 1), y: [56.09, 58.85, 55.48, 58.79] },
  { x: new Date(2025, 11, 1), y: [58.78, 59.65, 58.23, 59.05] },
  { x: new Date(2026, 0, 1), y: [59.37, 61.11, 59.35, 60.34] },
  { x: new Date(2026, 1, 1), y: [60.40, 60.52, 56.71, 56.93] },
  { x: new Date(2026, 2, 1), y: [57.02, 59.71, 56.04, 56.82] },
  { x: new Date(2026, 3, 1), y: [56.97, 59.62, 54.77, 59.30] },
  { x: new Date(2026, 4, 1), y: [59.11, 62.29, 59.10, 59.85] },
  { x: new Date(2026, 5, 1), y: [59.97, 60.11, 55.66, 58.42] },
  { x: new Date(2026, 6, 1), y: [58.34, 60.93, 56.75, 57.42] },
  { x: new Date(2026, 7, 1), y: [57.76, 58.08, 51.18, 54.71] },
  { x: new Date(2026, 8, 1), y: [54.80, 61.42, 53.18, 57.35] },
  { x: new Date(2026, 9, 1), y: [57.56, 63.09, 57.00, 62.99] },
  { x: new Date(2026, 10, 1), y: [62.89, 63.42, 59.72, 61.76] },
  { x: new Date(2026, 11, 1), y: [61.71, 64.15, 61.29, 63.04] }
];
var options = {
  chart: {
    height: 350,
    type: "candlestick",
  },
  series: [{
    data: seriesData
  }],
  stroke: {
    width: 1
  },
  xaxis: {
    type: "datetime"
  }
};
adminkit.apexcharts("#apexcharts-candlestick", function () {
  return options;
});
</script>
```
```tsx code title="src/components/price-chart.tsx"
"use client";

import { ApexChart } from "@/components/plugins/apexcharts";

// One candle per month: y is [open, high, low, close]
const prices = [
  { x: new Date(2025, 1, 1), y: [51.98, 56.29, 51.59, 53.85] },
  { x: new Date(2025, 2, 1), y: [53.66, 54.99, 51.35, 52.95] },
  { x: new Date(2025, 3, 1), y: [52.96, 53.78, 51.54, 52.48] },
  { x: new Date(2025, 4, 1), y: [52.54, 52.79, 47.88, 49.24] },
  { x: new Date(2025, 5, 1), y: [49.1, 52.86, 47.7, 52.78] },
  { x: new Date(2025, 6, 1), y: [52.83, 53.48, 50.32, 52.29] },
  { x: new Date(2025, 7, 1), y: [52.2, 54.48, 51.64, 52.58] },
  { x: new Date(2025, 8, 1), y: [52.76, 57.35, 52.15, 57.03] },
  { x: new Date(2025, 9, 1), y: [57.04, 58.15, 48.88, 56.19] },
  { x: new Date(2025, 10, 1), y: [56.09, 58.85, 55.48, 58.79] },
  { x: new Date(2025, 11, 1), y: [58.78, 59.65, 58.23, 59.05] },
  { x: new Date(2026, 0, 1), y: [59.37, 61.11, 59.35, 60.34] },
  { x: new Date(2026, 1, 1), y: [60.4, 60.52, 56.71, 56.93] },
  { x: new Date(2026, 2, 1), y: [57.02, 59.71, 56.04, 56.82] },
  { x: new Date(2026, 3, 1), y: [56.97, 59.62, 54.77, 59.3] },
  { x: new Date(2026, 4, 1), y: [59.11, 62.29, 59.1, 59.85] },
  { x: new Date(2026, 5, 1), y: [59.97, 60.11, 55.66, 58.42] },
  { x: new Date(2026, 6, 1), y: [58.34, 60.93, 56.75, 57.42] },
  { x: new Date(2026, 7, 1), y: [57.76, 58.08, 51.18, 54.71] },
  { x: new Date(2026, 8, 1), y: [54.8, 61.42, 53.18, 57.35] },
  { x: new Date(2026, 9, 1), y: [57.56, 63.09, 57.0, 62.99] },
  { x: new Date(2026, 10, 1), y: [62.89, 63.42, 59.72, 61.76] },
  { x: new Date(2026, 11, 1), y: [61.71, 64.15, 61.29, 63.04] },
];

export function PriceChart() {
  return (
    <div className="position-relative" style={{ minHeight: 365 }}>
      <ApexChart
        options={() => ({
          chart: { height: 350, type: "candlestick" },
          series: [{ data: prices }],
          stroke: { width: 1 },
          xaxis: { type: "datetime" },
        })}
      />
    </div>
  );
}
```

```tsx title="src/app/(dashboard)/markets/page.tsx"
import { PriceChart } from "@/components/price-chart";
import { pageMetadata } from "@/lib/site";

export const metadata = pageMetadata("/markets");

export default function MarketsPage() {
  return (
    <div className="card">
      <div className="card-header">
        <h2 className="card-title mb-0">LTC/BTC</h2>
      </div>
      <div className="card-body">
        <PriceChart />
      </div>
    </div>
  );
}
```

List `/markets` in `src/data/pages.json`, where `pageMetadata()` reads its title and description. Mind the dates in the example: JavaScript counts months from 0, so `new Date(2025, 1, 1)` is 1 February 2025.

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `options` | `(theme: Theme) => ApexOptions` | | The ApexCharts options, with `series` and `chart.type`. Called again with the new colors when the color mode changes |

## Data

Each point is `{ x, y }`. `x` is the date of the period, and `y` holds the prices in the order open, high, low, close.

Prices change, but AdminKit for Next.js is a static export (`output: "export"`). A server component page runs at build time, so prices passed from it are those of the last build. For current prices, fetch them in the client component, for example in a `useEffect`. Keep the chart in its skeleton state until they arrive:

```tsx title="src/components/price-chart.tsx"
"use client";

import { useEffect, useState } from "react";
import { ApexChart } from "@/components/plugins/apexcharts";
import { Skeleton } from "@/components/ui/skeleton";

type Candle = { x: number; y: [number, number, number, number] };

export function PriceChart() {
  const [prices, setPrices] = useState<Candle[] | null>(null);

  useEffect(() => {
    fetch("https://api.example.com/ltc-btc/monthly")
      .then((response) => response.json())
      .then(setPrices);
  }, []);

  return (
    <div className="position-relative" style={{ minHeight: 365 }}>
      {prices ? (
        <ApexChart
          options={() => ({
            chart: { height: 350, type: "candlestick" },
            series: [{ data: prices }],
            xaxis: { type: "datetime" },
          })}
        />
      ) : (
        <Skeleton />
      )}
    </div>
  );
}
```

The AI and CRM dashboards render a `Skeleton` the same way while their data is not ready.

## Candle colors

ApexCharts draws candlesticks in its own green and red, not in the series colors of the wrapper. `plotOptions.candlestick.colors` takes the theme colors instead, so the candles follow the color mode:

```tsx
plotOptions: {
  candlestick: {
    colors: { upward: theme.success, downward: theme.danger },
  },
},
```

## Accessibility

- A rising and a falling candle have the same shape. Only the color differs. Put the latest price and its change in text, as the stat cards of the crypto dashboard do.
- The OHLC values of a candle show in the tooltip on hover. Add a table where exact prices matter.
- Other props of `ApexChart` go to its `<div>`: `role="figure"` with an `aria-label` names the chart.

## Related

- [React candlestick chart](/react/docs/charts/candlestick-chart/): the same chart in AdminKit for React (Vite)
- [Bootstrap 5 candlestick chart](/bootstrap/docs/charts/candlestick-chart/): the ApexCharts example of the HTML version
- [Chart setup](/nextjs/docs/charts/overview/): the `ApexChart`, `ChartJs` and `VectorMap` client components
- [Next.js area chart](/nextjs/docs/charts/area-chart/): a value over time, filled
- [Crypto dashboard](https://nextjs-demo.adminkit.io/dashboard-crypto) and [ApexCharts demo](https://nextjs-demo.adminkit.io/charts-apexcharts)

---

Canonical HTML page: https://adminkit.io/nextjs/docs/charts/candlestick-chart/

Site overview for agents: https://adminkit.io/llms.txt (expanded: https://adminkit.io/llms-full.txt) · Documentation: https://adminkit.io/bootstrap/docs/ · Questions: support@adminkit.io
