Design and interface · Edition No. 1 · 21 Aug 2026

vercel/satori

A library that renders a subset of HTML and CSS into an SVG image.

← Design and interfaceRead the whole edition →
Satori: page code turned into a picture. Renders a subset of HTML and CSS as an SVG image.

13.9k stars · MPL-2.0 · 0.33.4 (2026-08-24) · Track this in Rising ↗

Turns HTML/CSS into images — mass-produce thumbnail variants and blog OG images from one template.

Verified27 Oct 2026

Radar check

What we found when we opened it. Every bar is one fact, with its date.

Alive100

Last code pushed 23 Oct 2026, 4 days before this check.

Releases100

Latest release 0.63.2 on 20 Oct 2026.

Maturity70

Public since January 2022, a little over 4 years.

Adoption83

14,135 stars and 395 forks.

Activity85

116 commits and 21 new issues in the last 90 days.

Community80

79 contributors. 116 pull requests merged in 90 days.

Security80

A security policy says how to report a problem. 1 published security advisory.

Licence MPL-2.0: free to use, even inside paid software; changes to this project itself must be sharedSetup effort 3 of 5Payoff 4 of 5
How the bars are scored
  • Alive. Days since the last code push: a week or less 100, a month 90, three months 70, six months 50, a year 30, eighteen months 15, older 0.
  • Releases. Age of the latest GitHub release, on a similar scale; no bar when the project publishes no releases.
  • Maturity. Age of the project: eight years 100, five 90, three 70, two 55, one 40, six months 25, younger 10.
  • Adoption. Stars on a log scale: 100,000 stars is 100, 10,000 is 80, 1,000 is 60, 100 is 40.
  • Activity. Commits in the last 90 days: 300 or more 100, 100 85, 30 65, 10 45, any 25.
  • Community. People who have contributed: 100 or more 100, 30 80, 10 60, 5 40, 2 25, one 10.
  • Security. A published security policy 80, none 40; published advisories are listed, not scored.

Checked by Repo Radar on 27 Oct 2026 from the repository on GitHub. Covered in Edition 1.

▶Repo detailsthe review · specs · pros & cons · install

What it does

You call it from JavaScript with an element and a size, and it returns the image as SVG text. SVG is an image format made of shapes and text rather than pixels, so it stays sharp at any size. You pass it the font files you want, which is how non-Latin alphabets are handled. It renders in milliseconds and needs no browser and no graphics card. It is the engine behind the automatic preview images on Vercel's own service. What it does not do is produce PNG files directly, and it does not support all of CSS: only a subset is implemented, so complicated grid layouts and visual filters behave differently or not at all. For a PNG you pass its output to a second library.

Why it matters

Who it suits. Anyone who needs many versions of the same image: video thumbnails with different headlines, preview images for every article, the same picture in two alphabets. It suits a team that already writes JavaScript, because this is a building block and not an application. Skip it if you need one image, because design software will be faster. Skip it too if the design depends on CSS features outside its subset, because finding out which ones are missing takes longer than drawing the thing.

Verdict. Worth an hour if images are a repeated chore, and nothing at all if they are not. The honest limit is in the name of the thing: it is a rendering primitive, so you write a small wrapper around it before it does anything useful. Once that wrapper exists, a new variation costs one line. The npm package is at version 0.47.1 and code landed on 2 October 2026, so it is current, and MPL-2.0 is a real open-source licence with no paid tier carved out. Two notes. Non-Latin alphabets render correctly, but only if you supply a font file that contains those letters, which is easy to forget. And it does nothing about testing which image works better: that still happens wherever the images are published.

Stars13.9k
LicenceMPL-2.0
Latest0.33.4 (2026-08-24)checked 7 Sep 2026
Written inTypeScript
Summary (Key Points)from the README
Key features
  • JSX input: Renders JSX elements that are pure and stateless. React hooks such as useState and useEffect are not supported.
  • Default SVG output: The example renders into a 600×400 SVG string. Converting to PNG is done with Sharp, which draws SVG with librsvg.
  • Flexbox, Grid and block layout: Uses Taffy for these layouts and its own inline layout for text. Most common CSS properties are supported, and a detailed property-by-property table lists the differences from browsers.
  • OpenType and typography: HarfBuzz text shaping enables features such as ligatures, small caps, stylistic sets (ss01-ss20) and contextual alternates through font-feature-settings.
  • Fonts: Accepts TTF, OTF, WOFF and WOFF2. Variable fonts render at their default instance, such as the regular weight.
  • Embedded text: By default, text is written as SVG path data, so the output does not need font files. Setting embedFont to false uses `<text>` instead.
  • Emoji and locales: graphemeImages maps graphemes to images that are resized to a square matching the font size. The lang attribute selects locale-specific rendering.
  • Experimental WebGL canvas and perspective: Available only from satori/experimental. The WebGL canvas defaults to 300×150, and perspective is drawn exactly there.
Ways to install
Platform or methodWhat it needsEffort
Browser, Node.js (>= 16) or Web WorkersFont data as ArrayBuffer (web) or Buffer (Node.js). The WASM layout engine is bundled as base64 and loaded at runtime.Low
Standalone buildDownload layout.wasm yourself and provide it, for example with fetch from the CDN or fs.readFile in Node.js.Medium
Experimental WebGL canvas in Node.js 20.16+A WebGL2 build of headless-gl, such as an ANGLE + SwiftShader build, installed in your project.High
Important
  • Limited HTML and CSS: Satori is not a full CSS engine. It does not guarantee output that matches the browser exactly, and table, ruby, subgrid, masonry and many pseudo-elements are unsupported.
  • Strict inline styles: An invalid inline style throws and fails the whole render unless onStyleError is set.
  • Font requirement: Any rendered text needs a font passed in. Only the fonts in the fonts option are used, and generic families such as serif do not select a font.
  • No scrollbars: Scrollbars are never drawn and take no space.
  • Experimental features: The WebGL canvas and exact perspective may change or be removed in any release.
  • Perspective cost: Perspective is split into many triangles, which makes the SVG larger and slower to render. An element can be drawn up to a few hundred times.
  • Colour conversion: Modern colour functions are converted to rgb() or rgba() by default, so some renderers may show different results unless convertColors is set to false.
  • Standalone WASM: The standalone build will not run until you load layout.wasm yourself.
  • Node WebGL: If you bundle server code, keep gl external and include its files in the deployment.

Written by an AI model from the project’s README; not part of the review, and it can be wrong.

Setup effort
3 / 5
Payoff
4 / 5
Good
  • Many variations of one image cost one line each, including versions in different alphabets.
  • No subscription, no graphics card and no browser: it is a library that runs in milliseconds.
  • The same template can produce both video thumbnails and web page preview images, so one design covers both.
Watch for
  • It is a building block, not an application, so you write a wrapper before it is useful.
  • Only part of CSS is implemented, and complex layouts and filters differ quietly from a browser.
  • It returns SVG only, so a PNG needs a second library in the chain.
Replaces

The same template then produces the OG images for your blog posts, so the site and the channel finally look like one brand instead of two.

Install
npm install satori
Screenshots
vercel/satori: GitHub preview card

On Stack Radar: Design & Creative › Branding & Graphic Design › Graphic Design.

Get the next edition in your inbox

A dozen repositories, opened and checked. The licence read, the last release dated, and the ones that did not make it named with the reason. It is the half most lists leave out.

No tracking pixels. One click to leave. The archive stays free either way.

We use your address to send the edition and nothing else. Confirm by email, leave in one click. How we handle it.