Server side rendering

ApexCharts fully supports server-side rendering for Next.js, Nuxt, SvelteKit, Astro, and other modern meta-frameworks. Charts rendered on the server produce static SVG that is immediately visible to users and web crawlers, with full interactivity restored on the client via hydration.

Package Entry Points

Two dedicated entry points cover the SSR workflow:

ImportEnvironmentWhat it provides
apexcharts/ssrNode.js / serverrenderToString(), renderToHTML()
apexcharts/clientBrowserhydrate(), hydrateAll(), isHydrated()
apexchartsBrowser (full)Standard full bundle, no SSR methods

Server-Side Rendering

Use renderToHTML() to generate hydration-ready HTML. It embeds the chart configuration in the output so the client can fully restore interactivity without re-fetching data.

// server.js (Node.js / any SSR framework)
import ApexCharts from 'apexcharts/ssr'

const html = await ApexCharts.renderToHTML(
  {
    series: [{ name: 'Sales', data: [30, 40, 35, 50, 49, 60, 70] }],
    chart:  { type: 'bar' },
    xaxis:  { categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul'] }
  },
  { width: 600, height: 350 }
)

// html is a self-contained string ready to embed in your page:
// <div class="apexcharts-ssr-wrapper" data-apexcharts-hydrate
//      data-apexcharts-config="...">
//   <svg ...>...</svg>
// </div>

renderToHTML() Options

OptionTypeDefaultDescription
widthnumber400Chart width in pixels
heightnumber300Chart height in pixels
scalenumber1SVG scale factor (useful for high-DPI output)
classNamestring''Additional CSS class added to the wrapper div

renderToString() — SVG Only

Use renderToString() when you only need the raw SVG string, for example to save to a file, pipe to a PDF renderer, or embed inside your own wrapper element.

import ApexCharts from 'apexcharts/ssr'

const svg = await ApexCharts.renderToString(
  {
    series: [{ data: [10, 41, 35, 51, 49, 62, 69, 91, 148] }],
    chart:  { type: 'line' }
  },
  { width: 800, height: 400 }
)

// svg is a plain SVG string
// '<svg xmlns="http://www.w3.org/2000/svg" ...>...</svg>'

Client-Side Hydration

Once the server-rendered HTML is in the browser, call hydrate() or hydrateAll() to restore full interactivity — tooltips, zoom, pan, legend toggling, and all other interactions.

// client.js (browser only)
import ApexCharts from 'apexcharts/client'

// Hydrate a single chart
const el = document.getElementById('my-chart')
const chart = ApexCharts.hydrate(el)

// Or hydrate every chart on the page at once
const charts = ApexCharts.hydrateAll()

Hydrate All on DOM Ready

import ApexCharts from 'apexcharts/client'

document.addEventListener('DOMContentLoaded', () => {
  ApexCharts.hydrateAll()
})

hydrateAll() with a Custom Selector

By default hydrateAll() targets every element with data-apexcharts-hydrate. Pass a CSS selector to restrict hydration to a subset of elements.

// Only hydrate charts inside the dashboard section
ApexCharts.hydrateAll('#dashboard [data-apexcharts-hydrate]')

Applying Client-Side Overrides on Hydration

Pass a clientOptions object as the second argument to override parts of the SSR configuration when hydrating. Common uses: re-enabling animations, adding event handlers, or changing theme for the interactive version.

import ApexCharts from 'apexcharts/client'

ApexCharts.hydrateAll('[data-apexcharts-hydrate]', {
  chart: {
    animations: { enabled: true, speed: 400 }
  },
  theme: { mode: 'dark' }
})

Animations are automatically re-enabled on hydration unless you explicitly set animations.enabled: false in clientOptions.

Checking Hydration State

import ApexCharts from 'apexcharts/client'

const el = document.getElementById('my-chart')

if (ApexCharts.isHydrated(el)) {
  console.log('Chart is already interactive')
} else {
  ApexCharts.hydrate(el)
}

Hydration Events

Each element dispatches an apexcharts:hydrated custom event when hydration completes successfully. Listen to it if you need to run code after the chart is interactive.

const el = document.getElementById('my-chart')

el.addEventListener('apexcharts:hydrated', (e) => {
  const { chart } = e.detail   // the ApexCharts instance
  console.log('Chart ready:', chart)
})

ApexCharts.hydrate(el)

Next.js Example

// app/page.jsx (Server Component)
import ApexCharts from 'apexcharts/ssr'

export default async function Page() {
  const chartHTML = await ApexCharts.renderToHTML(
    {
      series: [{ name: 'Monthly Revenue', data: [31, 40, 28, 51, 42, 109, 100] }],
      chart:  { type: 'area' },
      xaxis:  { categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul'] }
    },
    { width: 700, height: 350 }
  )

  return (
    <main>
      <h1>Dashboard</h1>
      <div dangerouslySetInnerHTML={{ __html: chartHTML }} />
      <ClientHydrator />
    </main>
  )
}
// app/ClientHydrator.jsx ('use client')
'use client'
import { useEffect } from 'react'
import ApexCharts from 'apexcharts/client'

export default function ClientHydrator() {
  useEffect(() => {
    ApexCharts.hydrateAll()
  }, [])
  return null
}

Nuxt Example

// server/api/chart.js
import ApexCharts from 'apexcharts/ssr'

export default defineEventHandler(async () => {
  const html = await ApexCharts.renderToHTML(
    {
      series: [{ data: [10, 41, 35, 51, 49, 62, 69] }],
      chart:  { type: 'line' }
    },
    { width: 600, height: 300 }
  )
  return { html }
})
<!-- pages/index.vue -->
<template>
  <div v-html="chartHtml" />
</template>

<script setup>
import ApexCharts from 'apexcharts/client'

const { data } = await useFetch('/api/chart')
const chartHtml = data.value.html

onMounted(() => {
  ApexCharts.hydrateAll()
})
</script>

How the HTML Output Is Structured

renderToHTML() returns a wrapper div containing the static SVG and a base64-encoded copy of the chart configuration. The client uses the encoded config to reconstruct the fully interactive chart on hydration — no server round-trip needed.

<div class="apexcharts-ssr-wrapper"
     data-apexcharts-hydrate
     data-apexcharts-config="eyJzZXJpZXMiOi4uLn0=">
  <svg xmlns="http://www.w3.org/2000/svg" ...>
    <!-- full chart SVG -->
  </svg>
</div>

After hydration, the element receives data-apexcharts-hydrated="true" and the data-apexcharts-config attribute is removed.