# Server rendering (SSR)

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

Source: https://82chart.com/en/docs/ssr/

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.

```js
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 argument | Default | What it does |
| --- | --- | --- |
| `width` | 640 | Width (px) |
| `height` | automatic | Total height (px); without it the plot is width × 0.5625 (`aspectRatio`) |
| `theme` | 'light' | `'light' \| 'dark'` |
| `header` | true | Include the card header, legend and footnote |
| `idPrefix` | automatic | Avoid id clashes with several SVGs on one page |

## Cloudflare Workers

```js
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

```html
---
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.

> Servers mostly run on UTC. For charts with dates, set a zone such as `timeZone: 'Asia/Seoul'` so the days match what the browser draws. See [Numbers and dates](https://82chart.com/en/docs/numbers-dates/).

> A server-rendered SVG is a picture. For tooltips and zoom, draw it again in the browser with `createChart`. The screen-reader summary is in its `aria-label` and `<title>`.
