vercel/satori

★ 13,941⑂ 0

Enlightened library to convert HTML and CSS to SVG

13,941Star
0Fork
0Watch
0Issue
TypeScriptLanguage
-License
Created · last push · repository size 0 KB · default branch -

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 docs →
> To use it in Next.js, take a look at the Open Graph Image Generation examples →

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(

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:

''

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.


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 }) => (

{children}
)

const svg = await satori( hello, world, 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 ` HTML element, the cursor CSS property are not in consideration. And you can't use tags or external resources via or `.

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 to embed images. However, width, and height attributes are recommended to set:

await satori(
  ,
  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(
  ,
  // 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:

Property Property Expanded Supported Values Example
CSS Variables Supported, including --var-name declaration and var(--var-name) usage with fallback values Example
display flex, block, contents, none, -webkit-box, default to flex. Use flex, contents, or none for div elements with multiple child nodes.
position relative, static and absolute, default to relative
color Supported
margin
marginTopSupported
marginRightSupported
marginBottomSupported
marginLeftSupported
Position
topSupported
rightSupported
bottomSupported
leftSupported
Size
widthSupported
heightSupported
Min & max size
minWidthSupported except for min-content, max-content and fit-content
minHeightSupported except for min-content, max-content and fit-content
maxWidthSupported except for min-content, max-content and fit-content
maxHeightSupported 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
borderTopLeftRadiusSupported
borderTopRightRadiusSupported
borderBottomLeftRadiusSupported
borderBottomRightRadiusSupported
ShorthandSupported, i.e. 5px, 50% / 5px
cornerShape
Valuesround, squircle, square, bevel, scoop, notch, and superellipse()
Corner longhands (cornerTopLeftShape, cornerTopRightShape, ...)Supported
Side shorthands (cornerTopShape, cornerRightShape, ...)Supported. Corner shapes apply when the corresponding borderRadius is nonzero.
Flex
flexDirectioncolumn, row, row-reverse, column-reverse, default to row
flexWrapwrap, nowrap, wrap-reverse, default to nowrap
flexGrowSupported
flexShrinkSupported
flexBasisSupported except for auto
alignItemsstretch, center, flex-start, flex-end, baseline, normal, default to stretch
alignContentSupported
alignSelfSupported
justifyContentSupported
gapSupported
Font
fontFamilySupported
fontSizeSupported
fontWeightSupported
fontStyleSupported
fontFeatureSettingsSupported via HarfBuzz text shaping. Enables OpenType features like ligatures, small caps, stylistic sets, etc.
Text
tabSizeSupported
textAlignstart, end, left, right, center, justify, default to start
textIndentSupported, including negative values (hanging indent)
textTransformnone, lowercase, uppercase, capitalize, defaults to none
textOverflowclip, ellipsis, defaults to clip
textDecorationSupport line types underline and line-through, and styles dotted, dashed, double, solidExample
textShadowSupported
lineHeightSupported
letterSpacingSupported
whiteSpacenormal, pre, pre-wrap, pre-line, nowrap, defaults to normal
wordBreaknormal, break-all, break-word, keep-all, defaults to normal
textWrapwrap, balance, defaults to wrap
Background
backgroundColorSupported, single value
backgroundImagelinear-gradient, repeating-linear-gradient, radial-gradient, repeating-radial-gradient, url, single value
backgroundPositionSupport single value
backgroundSizeSupport cover, contain, auto, and two-value sizes i.e. 10px 20%Example
backgroundClipborder-box, text
backgroundRepeatrepeat, repeat-x, repeat-y, no-repeat, defaults to repeat
transform
Translate (translate, translateX, translateY)Supported
RotateSupported
Scale (scale, scaleX, scaleY)Supported
Skew (skew, skewX, skewY)Supported
transformOrigin Support one-value and two-value syntax (both relative and absolute values)
objectFit Supported Example
objectPosition Supports keywords (top, bottom, left, right, center), percentages (e.g., 25% 75%), lengths (e.g., 10px 20px), and mixed values (e.g., left 20%). Defaults to center (50% 50%). Example
opacity Supported
boxSizing Supported
boxShadow Supported
overflow visible and hidden, default to visible
filter Supported
backdropFilter Supports chained blur(), brightness(), contrast(), drop-shadow(), grayscale(), hue-rotate(), invert(), opacity(), saturate(), and sepia()
clipPath Supports circle(), ellipse(), inset(), polygon(), path(), and shape(). shape() supports move, line, hline, vline, curve, smooth, arc, and close commands. Example
lineClamp Supported when the text element uses display: block. For WebKit-style clamping, use display: -webkit-box with WebkitLineClamp. Example
Mask
maskImagelinear-gradient(...), radial-gradient(...), url(...)Example
maskPositionSupportedExample
maskSizeSupport two-value size i.e. 10px 20%Example
maskRepeatrepeat, repeat-x, repeat-y, no-repeat, defaults to repeat<a href="https://og-playground.vercel.app/?share=nVbpjqNIEn6VkqXVzMg1AhtjQ-3MStwGA-Ywl9U_hssJ5jSHAbf63TdxdfXUzh4_FhllHF8cGZkm4usirKJ48bb4LUrvX8qXl7ab8vj3r19n-uUliVOQdG8vP61Q9G8_vb4LhzTqkr_IorStc3-C0ksejx_SmWbTJg67tCqhLqzyvig_tH6eglLs4qKdVXHZxc2H6tq3XXqZmAoKyzn-v6ovUG6mj_jtBVt_Ejnfs92i6Hdp4IcZaKq-jKCPvsl_jvzOf0sLH8RIXYK_B34bbzevqU0fjQE9CKCi4KOaVsJZAFK0PvMaQ3lwYbPiSNqzgHJV00BFqmk34XaGiEbucHlxslDqMNtRAJpyJkUpM0NTFAcXzqco6ztPUSbggs-8BTgY_AMvwl9UU9Qz_lPvPP0-WaiEz6zinkKoPwLIs9_lkGcATGEO-o6jTUANn3iKeJJ2F-6CJ58PJp8_ICFzA7QeFZqSbqHwBOW1zSeow62UY6HeAxNPzgKZnk18E7jfU2LHzbFMulBY5ZHAgVhYtUGpbGMWTT3HuHuFtZ35wLFRzyRScQ-2EDNEQkuKeaJaDM0GmJSLrNcrzGYQr5uDyFBA20vZ-VqbBuf98BkWRqGZUhXtjeGYEvcIizC5DB9yQU7niRiPpwyXH9QkP8RJdqF9unrEDo56Luig_fXD9yf_3NlVr2GRw3zye5DS01nwtp4j3SNXJ8VU_IH_eD9ygfjifEVTf2-gIVvd5TUO8-CzYC3l8rNWJOo750J-cHBfRKqB6rMf4t2-1mDsPCiN5Bn_uhk15t3umJGT79h9JPCQJ_tP9oSM_YfcP-rGwFrAPViZIUAbiH2v97P-p81BsHcJDc-ZWvGSwfHWkRZUm-8UDuWsMsJM7ITXvl8YYxpVaW

More Image Trending projects