<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Andrey Blinov</title>
    <description>The latest articles on DEV Community by Andrey Blinov (@aablinov).</description>
    <link>https://dev.to/aablinov</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F283722%2Ffa81d063-83dc-45a6-9faa-0fb63d9d03dd.jpeg</url>
      <title>DEV Community: Andrey Blinov</title>
      <link>https://dev.to/aablinov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aablinov"/>
    <language>en</language>
    <item>
      <title>Open Graph image generation on the fly with Ruby</title>
      <dc:creator>Andrey Blinov</dc:creator>
      <pubDate>Tue, 11 May 2021 18:07:52 +0000</pubDate>
      <link>https://dev.to/aablinov/open-graph-image-generation-on-the-fly-with-ruby-48o4</link>
      <guid>https://dev.to/aablinov/open-graph-image-generation-on-the-fly-with-ruby-48o4</guid>
      <description>&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;At &lt;a href="https://wannadocs.com" rel="noopener noreferrer"&gt;Wannadocs&lt;/a&gt;, we're generating Open Graph tags for each article to make it looks as attractive as possible when sharing on social media or messengers.&lt;/p&gt;

&lt;p&gt;I didn't want to spend a lot of time on this feature, so I created a 1200x600px image, filled it with the color that a user specified as the primary color in the Knowledge Base theme, and added the title as white text.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkeo3m2uxcw5b2pywmjqt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkeo3m2uxcw5b2pywmjqt.png" alt="Screenshot 2021-05-10 at 10.50.24 AM"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It was operating like that for a whole year.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;A year later, I began to notice that large companies are moving in this direction. I was excited and wants to know how they do it.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;dev.to&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F86axblwh9vtdp1qx2dxv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F86axblwh9vtdp1qx2dxv.png" alt="99a51d06-1010-4d35-b120-52a4fb635df6"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;github.com&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmzjy44eojdqf86szi9v0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmzjy44eojdqf86szi9v0.png" alt="caddy-geoip"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I did a little investigation. Since the source code of the dev.to is open, I found out that Github and dev.to creating their previews in HTML and send them to a special service that renders previews through Headless Chromium. With the new knowledge, I decided to slightly improve our previews generating to keep it up with the smooth appearance and content.&lt;/p&gt;

&lt;p&gt;Since we sell the self-hosted version of Wannadocs, we're not suited to using the third-party service here, so we decided to stay on "libvips" + Ruby.&lt;/p&gt;

&lt;p&gt;Let's go!&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;First, you need to install all necessary packages on the server and build the "libvips" (Ansible playbook is doing this for me, so I tried to get just shell commands from there):&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here you can find the official manual on &lt;a href="https://libvips.github.io/libvips/install.html" rel="noopener noreferrer"&gt;how to build it&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Pay attention to these packages:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;fonts-open-sans&lt;/strong&gt; – don't forget about fonts otherwise you will get that:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbk2auuq2twqrnd4lvwav.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbk2auuq2twqrnd4lvwav.jpeg" alt="1_uP-3RRlrly7-K9_JLyuwFQ"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And &lt;strong&gt;libpango1.0-dev&lt;/strong&gt; – without this library Vips cannot properly write text. &lt;/p&gt;

&lt;h2&gt;
  
  
  Anatomy
&lt;/h2&gt;

&lt;p&gt;Our previews are very similar to Github:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhfheeeajmlqpveecnu2g.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhfheeeajmlqpveecnu2g.jpeg" alt="b707a690-5295-45ac-b0eb-bb7d5cf920d2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gray text&lt;/strong&gt; is a knowledge base name, in this case (&lt;a href="https://demo.wannadocs.com" rel="noopener noreferrer"&gt;Demo&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Big dark text&lt;/strong&gt; is an article title&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On the right&lt;/strong&gt; side knowledge base logo&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;At the bottom&lt;/strong&gt; 20px border is the primary color of the knowledge base&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;I'm also a big fan of jQuery-style DSL with returning of the “self” object from a method and chaining.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;With DSL I'm trying to reduce the inconvenience of creating image layout with code and make this snippet more portable from project to project.&lt;/p&gt;

&lt;p&gt;In Rails, I created a controller that serves up these images like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;As a result, we get Open Graph images for all social networks without unnecessary dependencies on third-party services and very fast generation, unfortunately at the cost of the inconvenience of image layout.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkh3z1fkx60gh755ont82.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkh3z1fkx60gh755ont82.png" alt="Screenshot 2021-05-10 at 11.51.39 AM"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;a href="https://wannadocs.com" rel="noopener noreferrer"&gt;Wannadocs&lt;/a&gt; - we make product knowledge bases for your customers, we have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Cool editor with support for markdown and embedded elements (YouTube, CodePen, Gist, Figma, Airtable etc.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Analytics by the article: views, likes, dislikes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Built-in full-text search&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Templates and customization&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SSL certificates in two clicks&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Amazing OpenGraph images for your links 😍&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Who has read to the end catch the promo code 10% discount: &lt;a href="https://wannadocs.com" rel="noopener noreferrer"&gt;dz74cdq&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
    </item>
  </channel>
</rss>
