9 ms·
Show HN: Satori – Convert HTML and CSS to SVG
- elefantastisch 4y agoThis seems really cool, but I don't understand the use cases. Someone help me out?
- steventey 4y agoYou can basically use this to generate Open Graph images programmatically for your websites really really fast (1-2ms)! Here's a blog post detailing how this works (using @vercel/og): https://vercel.com/blog/introducing-vercel-og-image-generation-fast-dynamic-social-card-images https://vercel.com/blog/introducing-vercel-og-image-generati...
- metadat 4y agoCould satori be used to convert a whole webpage into a single SVG image? Could be a (convoluted?) way to ensure an asset looks the same across all browsers..
- Jaydenaus 4y agoThis was the use case I had in mind. My company generates exports that are either PDF or PNG/JPEG images from the DOM using Puppeteer. We really wanted to support SVG but every option we explored had pretty significant rendering issues, meaning an entire rewrite in SVG would have been required.
- shuding 4y agoNo, Satori does not guarantee that the SVG will 100% match the browser-rendered HTML output. That's because Satori implements its own layout engine based on the SVG 1.1 spec. However, Satori generated result (SVG) is stable on all browsers.
- eyelidlessness 4y agoIs the SVG->PNG portion of the show handled by Satori as well, or separately as a part of the Vercel service? Asking because I’ve got code handling that part for this exact use case, which I’d be happy to either eliminate if I can use Satori, or I could clean up and open source my own solution if people would find it useful.
- leerob 4y agoThe SVG -> PNG part is handled by @vercel/og. Specifically, it uses Vercel Edge Functions + WebAssembly to handle generating images at the edge. https://vercel.com/docs/concepts/functions/edge-functions/og-image-generation https://vercel.com/docs/concepts/functions/edge-functions/og...
- eyelidlessness 4y agoThanks! Not to discourage anyone from using Vercel services if they’re interested (y’all are doing great stuff on this and lots of other fronts), but! I’d be remiss if I didn’t point out the unpublished-but-MIT-licensed repo I could find. For anyone else who’s curious it looks like the pertinent source[1] can be self-hosted. I’m on mobile so I’m gonna limit my peering into the source, but it appears to wrap Chromium to do the PNG generation. Quite a bit different from my solution (which takes SVG-producing JSX and anything producing CSS, and renders to PNG with Sharp). I’m curious how much overhead using Chromium adds, and whether alternatives like Sharp were considered. 1: https://github.com/vercel/og-image https://github.com/vercel/og-image
- styfle 4y agoSee this issue: https://github.com/vercel/og-image/issues/148 https://github.com/vercel/og-image/issues/148
- nawgz 4y agoThis is vaguely supported by the browser natively, although you do have to find a way to output the CSS that impacts the SVG itself. I recently made image export on some SVG charts that you could download as SVG and PNG and I was quite pleased I managed to do it without any library
- dsmmcken 4y agoThat's pretty cool. I've hand rolled an og-image generator with Automattic/node-canvas for a static site (Docusaurus) at build time. Edge is cool, but doing it at build time probably makes more sense for static sites. Looks like using Satori might have been easier to use then having to do all the canvas draw calls (which isn't all that bad either though). Edit: Nevermind. Actually looks like this wouldn't be self hostable in a github action. vercel/og doesn't run in a node runtime?
- meowtimemania 4y agoSatori does run in node runtime. vercel/og (a wrapper around Satori) does not support node
- julienreszka 4y agoCan be useful to generate invoices without dealing with pdf
- gillesjacobs 4y agoThis would have been great for that one time I found a html+css copy-paste script for styled multiple underlined text. Doing it in LaTeX/tikz directly would have taken me hours. The html+css looked fine, but to get it to a vector image as required by the journal was a pain: print to PDF, find out the lines aren't reproduced correctly, manually find a PDF printer with the right settings, convert to eps
- lazyjeff 4y agoSome of what looks challenging here is handling fonts. SVG would be so much better if there was a way to do font embedding. Even a minimal set of fonts would be amazing. Or if operating systems or libraries for SVG support could all commit to supporting a common set of fonts, like browsers did for web safe fonts. Think of how clunky the web would have been without those.
- alixanderwang 4y agoYou can embed fonts in SVG: https://oreillymedia.github.io/Using_SVG/extras/ch07-dataURI-fonts.html#:~:text=Today%2C%20the%20best%20approach%20for,URI%20font%20on%20the%20web https://oreillymedia.github.io/Using_SVG/extras/ch07-dataURI....
- asib 4y agoIn my experience, embedded fonts are handled very inconsistently (and often poorly) by different rendering engines.
- morley 4y agoIn particular: if you load an SVG in Chrome via an img tag, the webfont is not run because the environment tries to execute as little as possible. It'll instead use whatever fallback font is present on the system. Source: I just dealt with this problem a few weeks ago. I also spent all last week implementing a custom OG image in Canvas. Wish Satori had come out a week earlier!
- aidos 4y agoThat didn't sound right to me, and I've just checked that the fonts are loading for me. I wonder if you were embedding them in a way that didn't work? EDIT: here's how I'm doing the embedding <style type="text/css"> @font-face { font-family:FontName; src:url(data:font/otf;base64,T1RUTwAOAIAAAwBgQ0ZGIHKc...AAAAAAAAAAAA=) format("opentype"); } </style> I've passed by the Chrome SVG code a bit, and I've never seen anything to suggest there's an "SVG lite" type version in there. I imagine it's just painted to a bitmap and handed to the compositor like everything else (obviously a massive simplification).
- crazygringo 4y ago(Warning: bit of a tangent) Conceptually, I love this. Mainly because for some reason it irritates me than screenshots are bitmaps. Nearly everything in a user interface or document is vector-based, except for photographs and natural-media illustrations. The ability to capture part of a webpage as an SVG feels like a step forwards in preserving vector content. My real wish is that OS interfaces would be just as vector-based, where rendering to bitmap was just something the OS handled at the end. So a screenshot in macOS or Windows would similarly always be SVG.
- asadlionpk 4y agoI also wished that was true while working on a fast web-based remote desktop client. Imagine if instead of a video stream via VNC, the UI was HTML or SVG diffs. That would be really fast! RDP does something similar but on a much lower-level.
- crazygringo 4y agoYes! IIRC, RDP was originally based on simply sending over the GDI calls -- the Windows draw instructions -- directly. I've been told it moved away from that as networks got faster, interfaces became more GPU-accelerated, and video encoding became hardware-accelerated, so that now it's not much different from VNC. But I don't know when or to what extent, or if RDP still uses any draw instructions at all.
- mmastrac 4y agoRDP most likely uses privileged instrumentation to detect screen damage, rather than having to do a full framebuffer scan (or getting framebuffer damage bounds) to identify diffs.
- digitallyfree 4y agoModern RDP can use hardware h.264 encoding if your GPU supports it, and grabs the output from the framebuffer and streams it like a game streaming app does. I think the default RDP mode still sends the draw commands the old-fashioned way though.
- jjtheblunt 4y agoIs this not reminiscent of Display Postscript?
- an1sotropy 4y agoIn Display PostScript the clients emit PS as their interface and for graphical output - its execution of a self-contained page/screen description language from the outset. HTML and CSS are very much not that. I think if anything this is more akin to "Save [this web page] to PDF".
- searchableguy 4y agoDoes the tailwind support work with className declaration? I would like to use it with existing component library which is built using tailwind without making changes. Is that possible?
- 4lejandrito 4y agoThey have experimental support for taiwind: https://og-playground.vercel.app/?share=xVRNb9swDP0rgoahl6h2v4bOSLtDNwwDtsu2oy9yRNtq9WFIch0jyH8fJc-tEwTDbj0kJvlo8j1S1o5urABa0CwjP6yQtQRBKu7x3xrShtD5IssCl2qQRvTyfGN1hr_OGjDBZ5q7JwjSNJmHTZDW-GwTOJud0pRmLeRzaQjxYVRwt9tFm5AWZNOGgpxd5Pn7s9UUHKQI7VFMSN8pPmK0VrCdo9H-LN3UBrGNVb02M8qVbMy3ANpHCImCm6HH3gdZjw8Wgyb2P4QrvnlqnO2NeLDKOsSHVgaY4P2-NPfRiJJIGO5KWjWscXxkN3miVNKELzNiOGEMORItimQ7O5CB1b1SpBvZxSXptuw6othMezaRmsmyCsIAYEjHbl86YI_28lSLANvArraKeF0k-xrtGvWyyipBgkOJuDAW4gKm7CThY55PnoI6LNpgI99xc_8TuBhJsLiRZyDSfFpnKX6UN1FKhfDEyMayD3mO5X4F7gIZbe9I7QCQh-RI1go-nh9VWmft5avzMkkd2G2SGeeETqy6aH448bRDEEwL4lsu7HCQjOmctA5qTH9X0sV7J-f_113UrKwTGJkeDGdqUIHDNIIn4lV3XOtN3PDVNNr4ZU270CBkr6doOmLI7ysE_EpwTCDWGV9qy1DcSa1aYek3F5wE_J_WgzPxHbgzRFsH_9K79F7t2ZqfdEVtly4dWuxouklocZvnKzpdNbS4jo6Aqm9oUXPlYUVB20f5e-ziDYifWPSwTiT9RVcgaBFcD_v9Hw https://og-playground.vercel.app/?share=xVRNb9swDP0rgoahl6h2... Edit: Oh I re-read your comment and you want to know if they support classnames... then my answer is not what you need :(
- ramshorst 4y agoInterested in this too.
- aidos 4y agoInteresting. I was thinking that this was going to be a crazy amount of layout engine work, but now I look a little closer it appears the layout work is farmed out to yoga [0] (not trying to take away anything from the effort here). So this project is almost a wrapper around running yoga as a renderer and using SVG as a form of backend target? I say "appears" because the yoga landing page doesn't do a great job of explaining what it does. EDIT Just looking at some of the information about the font side of things and the naming is a little confusing. You set embedFont=false to use text instead of converting the text to paths. embedFont=true sounds a lot like it will embed the _font_ required to render the _text_ - but it kinda does the opposite. https://github.com/vercel/satori#font-embedding https://github.com/vercel/satori#font-embedding [0] https://github.com/facebook/yoga https://github.com/facebook/yoga
- seanwilson 4y agoYou can do something like this via the browser by printing the page to PDF then using Inkscape to convert that to SVG. I documented this here: https://www.checkbot.io/article/web-page-screenshots-with-svg/ https://www.checkbot.io/article/web-page-screenshots-with-sv.... There's a few caveats though like box-shadows getting converted into bitmaps and vectors not being grouped in layers like you'd expect, plus it's heavyweight if you're wanting to script it. I'm curious if Satori could be used to capture in-app client-side screenshots accurately.
- djbusby 4y agoThere was some Google properties that had some in-page tool to screenshot the page - wonder how they did that one?
- seanwilson 4y agoIt's all client-side apparently, essentially by writing a page renderer in JavaScript. See: https://stackoverflow.com/questions/4912092/using-html5-canvas-javascript-to-take-in-browser-screenshots https://stackoverflow.com/questions/4912092/using-html5-canv... https://github.com/niklasvh/html2canvas https://github.com/niklasvh/html2canvas
- oefrha 4y agoNote that html2canvas has a lot of limitations, since everything that needs to be rendered has to be implemented from scratch using canvas primitives. If you have (IIRC) shadows, more advanced CSS features, certain SVG icons, etc., your output will be pretty broken. I usually have to do DOM cloning and modify/hide the problematic parts before using html2canvas to generate an image. It’s incredibly annoying that screenshotting isn’t a DOM API, while the functionality is clearly there in DevTools. Edit: To add to the annoyance, iOS Safari is extremely stingy with canvas memory.
- account42 4y ago> It’s incredibly annoying that screenshotting isn’t a DOM API As if we needed more browser fingerprinting vectors.
- rockwotj 4y agoI recently implemented a similar concept to this for HTML emails at shortwave.com, it only works for the subset of non table emails (which we assume are marketing emails and you want to see the full HTML). It allows us to render stuff wayyy faster (especially on mobile where webviews are not cheap). We don't go all the way to pixel layout because we want to have some responsiveness, but it allows for heavily normalized emails (no more neon yellow on a green background with comic-sans font) and some other neat optimizations. Didn't use yoga but a from scratch implementation. A good starting point is let's build a browser engine [1]. I hope to blog about it at somepoint. [1]: https://limpet.net/mbrubeck/2014/08/08/toy-layout-engine-1.html https://limpet.net/mbrubeck/2014/08/08/toy-layout-engine-1.h...
- benschwarz 4y agoWe used this to generate dynamic share cards for our core web vitals checker tool (plug: https://calibreapp.com/tools/core-web-vitals-checker https://calibreapp.com/tools/core-web-vitals-checker). Previously new uncached requests for Open graph share-card images were generated in Chrome, sometimes taking up to 5 seconds to generate. (They were then stored in cache for 12 hrs). Because we're now using Satori powered og images, they render almost immediately and we don't have to own the problem of having Chrome deployed within the 50mb lambda limitation. I'm pretty happy about that.
- deleted 4y ago[deleted]
- petilon 4y agoConverting text to SVG is super hard. Flowing English text is easy enough, but when it comes to Unicode text, with languages such as Arabic and Indian languages, that's when it gets hard. I tried Satori, and it doesn't handle Unicode very well, particularly, combining characters.
- shuding 4y agoAdvanced text shaping isn’t implemented yet, where we plan to use Harfbuzz in the future.
- marsvin 4y agoAlright, I like this, almost a lot! In the 90's there was a vector graphics editor called Satori. It was something beyond the understanding of us neighbourhood kids. Something beyond the Paint (and Paintshop Pro). Now let's get back from the nostalgia trip...
- fractallyte 4y agoIllustrations were created using a vector graphics engine, and then rendered as a bitmap. The brushes looked 'painterly', but they were editable and scalable. So it was possible to take a postage-stamp sized picture and scale it up to billboard size without any loss of resolution. Watercolor paintings that were actually vectors? Yes, that's exactly what it offered! There was also some architectural trickery that enabled huge pictures to be loaded into the application on machines with limited RAM. The nearest software to this now is Synthetik Studio Artist (https://synthetik.com/ https://synthetik.com/).
- EugeneOZ 4y agoJSX, not HTML. Hate JSX.
- gnrlst 4y agoLove the project! Sorry to be pedantic, but the claim is technically false. You don't actually support HTML and CSS. You support JSX. As someone who doesn't use React due to the abomination of mixing html and css within the JS, do you have plans to actually support regular HTML and CSS? Or provide a dedicated transpiler? (I'm not familiar with the react ecosystem, so likely one already exists?)
- tngranados 4y agoThe claim is correct, it supports a subset of HTML and CSS[0]. You can even check the demo page[1], it has examples with HTML and inline styles. [0]: https://github.com/vercel/satori#html-elements https://github.com/vercel/satori#html-elements [1]: https://og-playground.vercel.app https://og-playground.vercel.app
- gnrlst 4y ago[0] "supports a limited subset of HTML and CSS features" (and it still requires jsx-esque syntax with curly braces) [1] uses JSX So, yeah, my comment still stands.
- shuding 4y agoJSX here is just a way to represent the HTML information because you can't write HTML in JavaScript. It is NOT required. But with the JSX representation, the lib doesn't have to parse it again, and it's using it as JSON, check the "Use without JSX" section in the docs: https://github.com/vercel/satori#use-without-jsx https://github.com/vercel/satori#use-without-jsx
- lloydatkinson 4y agoLooks great but as far as I know for some reason no site supporting OG previews support SVGs
- wslh 4y agoIs Satori including it's own HTML/CSS renderer or relying on a browser behind the scenes?
- shuding 4y agoIt does not rely on a browser. Satori itself includes a CSS parser/normalizer, a flexbox layout engine, a text layout engine and a SVG renderer.
- wslh 4y agoSo, I am really more courious, with a JS engine is it an almost complete browser (probably excluding some aspects)? Does it include transitions?