SkillAgentSearch skills...

Satori

Enlightened library to convert HTML and CSS to SVG

Install / Use

/learn @vercel/Satori
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Satori

Satori: Enlightened library to convert HTML and CSS to SVG.

Note

To use Satori in your project to generate PNG images like Open Graph images and social cards, check out our announcement and Vercel’s Open Graph Image Generation →

To use it in Next.js, take a look at the Next.js Open Graph Image Generation template →

Overview

Satori supports the JSX syntax, which makes it very straightforward to use. Here’s an overview of the basic usage:

// api.jsx
import satori from 'satori'

const svg = await satori(
  <div style={{ color: 'black' }}>hello, world</div>,
  {
    width: 600,
    height: 400,
    fonts: [
      {
        name: 'Roboto',
        // Use `fs` (Node.js only) or `fetch` to read the font as Buffer/ArrayBuffer and provide `data` here.
        data: robotoArrayBuffer,
        weight: 400,
        style: 'normal',
      },
    ],
  },
)

Satori will render the element into a 600×400 SVG, and return the SVG string:

'<svg ...><path d="..." fill="black"></path></svg>'

Under the hood, it handles layout calculation, font, typography and more, to generate a SVG that matches the exact same HTML and CSS in a browser.

<br/>

Documentation

JSX

Satori only accepts JSX elements that are pure and stateless. You can use a subset of HTML elements (see section below), or custom React components, but React APIs such as useState, useEffect, dangerouslySetInnerHTML are not supported.

Experimental: builtin JSX support

Satori has an experimental JSX runtime that you can use without having to install React. You can enable it on a per-file basis with @jsxImportSource pragmas. In the future, it will autocomplete only the subset of HTML elements and CSS properties that Satori supports for better type-safety.

/** @jsxRuntime automatic */
/** @jsxImportSource satori/jsx */

import satori from 'satori';
import { FC, JSXNode } from 'satori/jsx';

const MyComponent: FC<{ children: JSXNode }> = ({ children }) => (
  <div style={{ color: 'black' }}>{children}</div>
)

const svg = await satori(
  <MyComponent>hello, world</MyComponent>,
  options,
)

Use without JSX

If you don't have JSX transpiler enabled, you can simply pass React-elements-like objects that have type, props.children and props.style (and other properties too) directly:

await satori(
  {
    type: 'div',
    props: {
      children: 'hello, world',
      style: { color: 'black' },
    },
  },
  options
)

HTML Elements

Satori supports a limited subset of HTML and CSS features, due to its special use cases. In general, only these static and visible elements and properties that are implemented.

For example, the <input> HTML element, the cursor CSS property are not in consideration. And you can't use <style> tags or external resources via <link> or <script>.

Also, Satori does not guarantee that the SVG will 100% match the browser-rendered HTML output since Satori implements its own layout engine based on the SVG 1.1 spec.

You can find the list of supported HTML elements and their preset styles here.

Images

You can use <img> to embed images. However, width, and height attributes are recommended to set:

await satori(
  <img src="https://picsum.photos/200/300" width={200} height={300} />,
  options
)

When using background-image, the image will be stretched to fit the element by default if you don't specify the size.

If you want to render the generated SVG to another image format such as PNG, it would be better to use base64 encoded image data (or buffer) directly as props.src so no extra I/O is needed in Satori:

await satori(
  <img src="data:image/png;base64,..." width={200} height={300} />,
  // Or src={arrayBuffer}, src={buffer}
  options
)

CSS

Satori uses the same Flexbox layout engine as React Native, and it’s not a complete CSS implementation. However, it supports a subset of the spec that covers most common CSS features:

<table> <thead> <tr> <th>Property</th> <th>Property Expanded</th> <th>Supported Values</th> <th>Example</th> </tr> </thead> <tbody> <tr> <td colspan="2"><b>CSS Variables</b></td> <td>Supported, including <code>--var-name</code> declaration and <code>var(--var-name)</code> usage with fallback values</td> <td><a href="https://og-playground.vercel.app/?share=rVLRTsIwFP2V5hIzTbY4wBjTIC9oos-a8MJLt95tha4lXQfOZf9uOxwRlTeeentO7zntuW0h1RyBwoyL3UoRUtlG4mPb-pqQIIpsgSVGqZbaBJQEnJlNImsMwsOJAkVeWEeM4_hqAPeC2-IXxkW1laxxaCbxY0B9_SQMplZo5TjnU5dqYJkUuXq1WFaeQmXRDNS6rqzImoV2oPL-p3TC0k1udK34wt_c8aMsy46urutNfCIl08kPaPn9lvs47tGuW6m5L3w4x2RIn4VT3DFzfZLPTeBa5i8opQ7JUhvJZ7eu8x-Jv7lqw1TuUr2E-lmJaBKSUTaNx_H4vNqwQgh668dSAW2hHynQBxcNHGYO9M5vOCZ1DjRjssIQsNRr8d5s_Zey-37ndHy4z2WCHKg1NXYhWJa4E4W333tz6L4A">Example</a></td> </tr> <tr> <td colspan="2"><code>display</code></td> <td><code>flex</code>, <code>contents</code>, <code>none</code>, default to <code>flex</code></td> <td></td> </tr> <tr> <td colspan="2"><code>position</code></td> <td><code>relative</code>, <code>static</code> and <code>absolute</code>, default to <code>relative</code></td> <td></td> </tr> <tr> <td colspan="2"><code>color</code></td> <td>Supported</td> <td></td> </tr> <tr><td rowspan="5"><code>margin</code></td></tr> <tr><td><code>marginTop</code></td><td>Supported</td><td></td></tr> <tr><td><code>marginRight</code></td><td>Supported</td><td></td></tr> <tr><td><code>marginBottom</code></td><td>Supported</td><td></td></tr> <tr><td><code>marginLeft</code></td><td>Supported</td><td></td></tr> <tr><td rowspan="5">Position</td></tr> <tr><td><code>top</code></td><td>Supported</td><td></td></tr> <tr><td><code>right</code></td><td>Supported</td><td></td></tr> <tr><td><code>bottom</code></td><td>Supported</td><td></td></tr> <tr><td><code>left</code></td><td>Supported</td><td></td></tr> <tr><td rowspan="3">Size</td></tr> <tr><td><code>width</code></td><td>Supported</td><td></td></tr> <tr><td><code>height</code></td><td>Supported</td><td></td></tr> <tr><td rowspan="5">Min & max size</td></tr> <tr><td><code>minWidth</code></td><td>Supported except for <code>min-content</code>, <code>max-content</code> and <code>fit-content</code></td><td></td></tr> <tr><td><code>minHeight</code></td><td>Supported except for <code>min-content</code>, <code>max-content</code> and <code>fit-content</code></td><td></td></tr> <tr><td><code>maxWidth</code></td><td>Supported except for <code>min-content</code>, <code>max-content</code> and <code>fit-content</code></td><td></td></tr> <tr><td><code>maxHeight</code></td><td>Supported except for <code>min-content</code>, <code>max-content</code> and <code>fit-content</code></td><td></td></tr> <tr><td rowspan="5"><code>border</code></td></tr> <tr><td>Width (<code>borderWidth</code>, <code>borderTopWidth</code>, ...)</td><td>Supported</td><td></td></tr> <tr><td>Style (<code>borderStyle</code>, <code>borderTopStyle</code>, ...)</td><td><code>solid</code> and <code>dashed</code>, default to <code>solid</code></td><td></td></tr> <tr><td>Color (<code>borderColor</code>, <code>borderTopColor</code>, ...)</td><td>Supported</td><td></td></tr> <tr><td> Shorthand (<code>border</code>, <code>borderTop</code>, ...)</td><td>Supported, i.e. <code>1px solid gray</code><br/> </td><td></td></tr> <tr><td rowspan="6"><code>borderRadius</code></td></tr> <tr><td><code>borderTopLeftRadius</code></td><td>Supported</td><td></td></tr> <tr><td><code>borderTopRightRadius</code></td><td>Supported</td><td></td></tr> <tr><td><code>borderBottomLeftRadius</code></td><td>Supported</td><td></td></tr> <tr><td><code>borderBottomRightRadius</code></td><td>Supported</td><td></td></tr> <tr><td>Shorthand</td><td>Supported, i.e. <code>5px</code>, <code>50% / 5px</code></td><td></td></tr> <tr><td rowspan="11">Flex</td></tr> <tr><td><code>flexDirection</code></td><td><code>column</code>, <code>row</code>, <code>row-reverse</code>, <code>column-reverse</code>, default to <code>row</code></td><td></td></tr> <tr><td><code>flexWrap</code></td><td><code>wrap</code>, <code>nowrap</code>, <code>wrap-reverse</code>, default to <code>wrap</code></td><td></td></tr> <tr><td><code>flexGrow</code></td><td>Supported</td><td></td></tr> <tr><td><code>flexShrink</code></td><td>Supported</td><td></td></tr> <tr><td><code>flexBasis</code></td><td>Supported except for <code>auto</code></td><td></td></tr> <tr><td><code>alignItems</code></td><td><code>stretch</code>, <code>center</code>, <code>flex-start</code>, <code>flex-end</code>, <code>baseline</code>, <code>normal</code>, default to <code>stretch</code></td><td></td></tr> <tr><td><code>alignContent</code></td><td>Supported</td><td></td></tr> <tr><td><code>alignSelf</code></td><td>Supported</td><td></td></tr> <tr><td><code>justifyContent</code></td><td>Supported</td><td></td></tr> <tr><td><code>gap</code></td><td>Supported</td><td></td></tr> <tr><td rowspan="5">Font</td></tr> <tr><td><code>fontFamily</code></td><td>Supported</td><td></td></tr> <tr><td><code>fontSize</code></td><td>Supported</td><td></td></tr> <tr><td><code>fontWeight</code></td><td>Supported</td><td></td></tr> <tr><td><code>fontStyle</code></td><td>Supported</td><td></td></tr> <tr><td rowspan="13">Text</td></tr> <tr><td><code>tabSize</code></td><td>Supported</td><td></td></tr> <tr><td><code>textAlign</code></td><td><code>start</code>, <code>end</code>, <code>left</code>, <code>right</code>, <code>center</code>, <code>justify</code>, default to <code>start
View on GitHub
GitHub Stars13.2k
CategoryContent
Updated8h ago
Forks339

Languages

TypeScript

Security Score

100/100

Audited on Apr 6, 2026

No findings