
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 →
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(
hello, world
,
{
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.
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.
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 }) => (
{children}
)
const svg = await satori(
<MyComponent>hello, world</MyComponent>,
options,
)
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
)
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.
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="https://github.com/vercel/satori/raw/0.27.2/data:image/png;base64,..." width={200} height={300} />,
// Or src={arrayBuffer}, src={buffer}
options
)
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:
| Property | Property Expanded | Supported Values | Example |
|---|---|---|---|
| CSS Variables | Supported, including --var-name declaration and var(--var-name) usage with fallback values |
Example | |
display |
flex, contents, none, default to flex |
||
position |
relative, static and absolute, default to relative |
||
color |
Supported | ||
margin | |||
marginTop | Supported | ||
marginRight | Supported | ||
marginBottom | Supported | ||
marginLeft | Supported | ||
| Position | |||
top | Supported | ||
right | Supported | ||
bottom | Supported | ||
left | Supported | ||
| Size | |||
width | Supported | ||
height | Supported | ||
| Min & max size | |||
minWidth | Supported except for min-content, max-content and fit-content | ||
minHeight | Supported except for min-content, max-content and fit-content | ||
maxWidth | Supported except for min-content, max-content and fit-content | ||
maxHeight | Supported except for min-content, max-content and fit-content | ||
border | |||
Width (borderWidth, borderTopWidth, ...) | Supported | ||
Style (borderStyle, borderTopStyle, ...) | solid and dashed, default to solid | ||
Color (borderColor, borderTopColor, ...) | Supported | ||
Shorthand (border, borderTop, ...) | Supported, i.e. 1px solid gray
| ||
borderRadius | |||
borderTopLeftRadius | Supported | ||
borderTopRightRadius | Supported | ||
borderBottomLeftRadius | Supported | ||
borderBottomRightRadius | Supported | ||
| Shorthand | Supported, i.e. 5px, 50% / 5px | ||
| Flex | |||
flexDirection | column, row, row-reverse, column-reverse, default to row | ||
flexWrap | wrap, nowrap, wrap-reverse, default to wrap | ||
flexGrow | Supported | ||
flexShrink | Supported | ||
flexBasis | Supported except for auto | ||
alignItems | stretch, center, flex-start, flex-end, baseline, normal, default to stretch | ||
alignContent | Supported | ||
alignSelf | Supported | ||
justifyContent | Supported | ||
gap | Supported | ||
| Font | |||
fontFamily | Supported | ||
fontSize | Supported | ||
fontWeight | Supported | ||
fontStyle | Supported | ||
| Text | |||
tabSize | Supported | ||
textAlign | start, end, left, right, center, justify, default to start | ||
textIndent | Supported, including negative values (hanging indent) | ||
textTransform | none, lowercase, uppercase, capitalize, defaults to none | ||
textOverflow | clip, ellipsis, defaults to clip | ||
textDecoration | Support line types underline and line-through, and styles dotted, dashed, double, solid | Example | |
textShadow | Supported | ||
lineHeight | Supported | ||
letterSpacing | Supported | ||
whiteSpace | normal, pre, pre-wrap, pre-line, nowrap, defaults to normal | ||
wordBreak | normal, break-all, break-word, keep-all, defaults to normal | ||
textWrap | wrap, balance, defaults to wrap | ||
| Background | |||
backgroundColor | Supported, single value | ||
backgroundImage | linear-gradient, repeating-linear-gradient, radial-gradient, repeating-radial-gradient, url, single value | ||
backgroundPosition | Support single value | ||
backgroundSize | Support cover, contain, auto, and two-value sizes i.e. 10px 20% |
$ claude mcp add satori \
-- python -m otcore.mcp_server <graph>