chart

Docs › Frameworks and server

Server rendering (SSR)

renderToSVG makes an SVG string without a DOM: Node, Workers, Astro, e-mail and OG images.

The function that draws on screen also produces the SVG string, so a chart rendered on the server with renderToSVG, the one drawn in the browser and the file from toSVG() are identical. No DOM is needed: Node, Cloudflare Workers, Deno and Bun all work.

import { renderToSVG } from '@82chart/core';

const svg = renderToSVG(
  {
    type: 'line',
    language: 'en',          // there is no document language on a server
    timeZone: 'Asia/Seoul',  // servers mostly run on UTC: keep dates on the right day
    title: 'Weekly visitors',
    data: { labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'], series: [{ name: 'Visitors', data: [1820, 2140, 1990, 2410, 2290] }] },
  },
  { width: 640, height: 360, theme: 'light' },
);
// '<svg xmlns="http://www.w3.org/2000/svg" width="640" height="360" viewBox="0 0 640 360" role="img" aria-label="Line chart, Weekly visitors. …">…</svg>'
Second argumentDefaultWhat it does
width640Width (px)
heightautomaticTotal height (px); without it the plot is width × 0.5625 (aspectRatio)
theme'light''light' | 'dark'
headertrueInclude the card header, legend and footnote
idPrefixautomaticAvoid id clashes with several SVGs on one page

Cloudflare Workers

import { renderToSVG } from '@82chart/core';

export default {
  async fetch(req, env) {
    const rows = await env.DB.prepare('SELECT day, visits FROM stats ORDER BY day DESC LIMIT 14').all();
    const list = rows.results.reverse();
    const svg = renderToSVG({
      type: 'area', language: 'en', title: 'Visits, last 14 days',
      data: { series: [{ name: 'Visits', data: list.map((r) => [r.day, r.visits]) }] },
    }, { width: 800, height: 400 });
    return new Response(svg, { headers: { 'content-type': 'image/svg+xml; charset=utf-8', 'cache-control': 'max-age=300' } });
  },
};

Static sites such as Astro

---
import { renderToSVG } from '@82chart/core';
const svg = renderToSVG({ type: 'bar', language: 'en', data: { labels: ['A', 'B'], series: [{ data: [3, 5] }] } }, { width: 560 });
---
<figure set:html={svg} />

Idea: share images (OG)

A post or report page can use a chart with real numbers as its og:image: render a 1200×630 SVG with renderToSVG in a Worker, convert it with an SVG-to-PNG library (resvg-wasm, for example) and cache the result. Convert to PNG for e-mail too; most mail clients do not show SVG.