DocumentationNuxt Charts v3

Server-side Rendering

Learn how to handle server-side rendering with client-side-only charts in your Nuxt application.

Warning! Chart SVG is rendered on the client. The module ships SSR-safe stubs, but interactive drawing still happens after hydration.
The Nuxt module pre-bundles vccs and related deps to minimize SSR issues. If you still hit hydration problems, use the instructions below.

Solutions for SSR Compatibility

1. Use the .client.vue file naming convention

Create chart components with the .client.vue suffix to prevent them from being imported on the server side.

MyChart.client.vue
<template>
  <LineChart
    :data="data"
    :height="275"
    y-label="Sales"
    :x-num-ticks="4"
    :y-num-ticks="4"
    :categories="categories"
    :x-formatter="xFormatter"
    :grid-line-y="true"
    :legend-position="LegendPosition.TopRight"
  />
</template>

2. Use the ClientOnly wrapper

Wrap your chart components with the <ClientOnly> tag to ensure they only render on the client side.

client-only.vue
<ClientOnly>
  <YourChartComponent />
</ClientOnly>
Warning! Don't wrap individual chart components inside a component that already uses charts. Instead, wrap the entire parent component.

This will fail:

wrong-approach.vue
<div>
  <h2 class="font-bold text-lg text-highlighted tracking-wide py-1">
    This will fail
  </h2>
  <ClientOnly>
    <LineChart 
      :data="data"
      :height="275"
      y-label="Sales"
      :x-num-ticks="4"
      :y-num-ticks="4"
      :categories="categories"
      :x-formatter="xFormatter"
      :grid-line-y="true"
      :legend-position="LegendPosition.TopRight"
    />
  </ClientOnly>
</div>

This will work:

correct-approach.vue
<div>
  <ClientOnly>
    <MyChartWrapperComponent />
  </ClientOnly>
</div>

3. Disable SSR Globally in nuxt.config.ts

You can disable server-side rendering for your entire Nuxt app by setting ssr: false in your nuxt.config.ts:

nuxt.config.ts
export default defineNuxtConfig({
  ssr: false
})

Note! Disabling SSR globally is only recommended if your entire application does not require server-side rendering. For most use cases, prefer the .client.vue convention or <ClientOnly> wrapper for specific components.

4. Use defineAsyncComponent for Dynamic Import

You can dynamically import chart components using defineAsyncComponent to ensure they are only loaded on the client. This is especially useful for SSR compatibility:

async-component.ts
const MyChart = defineAsyncComponent(() => import('./MyChart.vue'))

Best Practices

✅ Use the .client.vue naming convention for chart components.

✅ Wrap entire components that contain charts with the <ClientOnly> tag.

❌ Don't nest <ClientOnly> tags within components that already use charts.