<?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: Mads Phikamphon</title>
    <description>The latest articles on DEV Community by Mads Phikamphon (@genvejen).</description>
    <link>https://dev.to/genvejen</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%2F330692%2Fa0aaa36c-c791-44c7-bcf6-ff982acbbd53.JPG</url>
      <title>DEV Community: Mads Phikamphon</title>
      <link>https://dev.to/genvejen</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/genvejen"/>
    <language>en</language>
    <item>
      <title>Creating an error reporting popup with Wordpress Flatsome and Contact Form 7</title>
      <dc:creator>Mads Phikamphon</dc:creator>
      <pubDate>Thu, 31 Aug 2023 03:08:08 +0000</pubDate>
      <link>https://dev.to/genvejen/creating-an-error-reporting-popup-with-wordpress-flatsome-and-contact-form-7-5fdm</link>
      <guid>https://dev.to/genvejen/creating-an-error-reporting-popup-with-wordpress-flatsome-and-contact-form-7-5fdm</guid>
      <description>&lt;p&gt;My website &lt;a href="https://www.modelprices.com/"&gt;Model Prices&lt;/a&gt; index model train prices from 1,200+ shops from all over the world.&lt;/p&gt;

&lt;p&gt;All the indexing is done by some big algorithms and just like any other code, things might go wrong once in a while.&lt;/p&gt;

&lt;p&gt;For example, a price might be indexed under the wrong model train model or I might index the wrong price amount.&lt;/p&gt;

&lt;p&gt;Most things that go wrong are caught by my algorithm and fixed automatically, but sometimes errors pass through without me noticing it.&lt;/p&gt;

&lt;p&gt;Not so good if you want to make a useful website 😅&lt;/p&gt;

&lt;h2&gt;
  
  
  Why an error reporting popup?
&lt;/h2&gt;

&lt;p&gt;To take care of the errors that pass through, I decided to make an error reporting popup. That is a link that the users can click, so a popup appears with room for describing the error and clicking submit to send me the report by email.&lt;/p&gt;

&lt;p&gt;First I started coding the popup myself, but then I realized that Flatsome, fantastic Wordpress theme I'm using, have a lot of built-in functionality. Including a simple way to make a popup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Show the popup
&lt;/h2&gt;

&lt;p&gt;First, I added the popup code to my product page code. That is the code to pages like &lt;a href="https://www.modelprices.com/p/roco-71976/"&gt;this one&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The notoriously thin Flatsome documentation shows the basic version of the lightbox code &lt;a href="https://docs.uxthemes.com/article/229-lightbox-shortcode"&gt;here&lt;/a&gt;, so I just modified that a bit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[lightbox id="lightbox_price_error" width="600px" padding="20px"]
    &amp;lt;h4&amp;gt;Found an error 😮&amp;lt;/h4&amp;gt;
[/lightbox]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since I added it to my product page code, I wrapped it in &lt;code&gt;do_shortcode()&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function fh_get_product_page_error_popup() {
    $popup_code = '[lightbox id="lightbox_price_error" width="600px" padding="20px"]
            &amp;lt;h4&amp;gt;Found an error 😮&amp;lt;/h4&amp;gt;
        [/lightbox]';

    return do_shortcode($popup_code);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Click to show the popup
&lt;/h2&gt;

&lt;p&gt;Now I had a first version of the popup that I could use to test things, i.e. see if the popup would actually appear or not.&lt;/p&gt;

&lt;p&gt;It was now time to make a link that my users could click on to show the popup. Again, easy to do thanks to Flatsome:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;b style='color:#000;'&amp;gt;Found an error? 😮&amp;lt;/b&amp;gt; &amp;lt;a href='#lightbox_price_error' class='fh-underline-link'&amp;gt;Please tell me&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I added this to link to the product page code too, so users now would see this when they clicked the "See Deal" buttons (or actually they would if I uploaded the code. My development if of course done locally, so I don't mess up the code my users are seeing).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dS2mdD6F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0gxd3j0danfiejaj58ka.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dS2mdD6F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0gxd3j0danfiejaj58ka.png" alt="Image description" width="375" height="329"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And when they clicked the link, the popup would appear:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--I4V1OzPL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dniuga29b7z25b6ich56.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I4V1OzPL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dniuga29b7z25b6ich56.png" alt="Image description" width="635" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Great stuff.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding the contact form
&lt;/h2&gt;

&lt;p&gt;The purpose of creating the popup is to allow my users to report errors, so now it was time to add a small contact form. Create the form with Contact Form 7 like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wXNTUJJe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v2roe5ju5mbfjpv4ylur.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wXNTUJJe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v2roe5ju5mbfjpv4ylur.png" alt="Image description" width="704" height="266"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And added the contact form to the popup by modifying the shortcode in my product page code like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function fh_get_product_page_error_popup() {
    $popup_code = '[lightbox id="lightbox_price_error" width="600px" padding="20px"]
            &amp;lt;h4&amp;gt;Found an error 😮&amp;lt;/h4&amp;gt;
            [contact-form-7 id="***" title="Price Error"]
        [/lightbox]';

    return do_shortcode($popup_code);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Testing again and now a nice form with two fields and a button appears when users click the link from above:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--a8NSmz6F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7r9wrttjqquedng5k9fl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--a8NSmz6F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7r9wrttjqquedng5k9fl.png" alt="Image description" width="635" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Sending data to the popup
&lt;/h2&gt;

&lt;p&gt;For the error reports to be useful, I needed to know which products and prices they belong too. Luckily Contact Form 7 forms can have hidden fields, so I added two of those. One for the product id and one for the price id, like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4k17qZyN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/71aekh08d2dloinm67qe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4k17qZyN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/71aekh08d2dloinm67qe.png" alt="Image description" width="704" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also edited the shortcode a bit, so it now had the two extra fields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function fh_get_product_page_error_popup() {
    $popup_code = '[lightbox id="lightbox_price_error" width="600px" padding="20px"]
            &amp;lt;h4&amp;gt;Found an error 😮&amp;lt;/h4&amp;gt;
            [contact-form-7 id="8edf729" title="Price Error" product_id="-" price_id="-"]
        [/lightbox]';

    return do_shortcode($popup_code);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Final step is to send the ids to the form when the popup is opened. This could be done by following &lt;a href="https://contactform7.com/getting-default-values-from-shortcode-attributes/"&gt;the instructions here&lt;/a&gt; - and when doing so, remembering to tag the fields in the contact form with &lt;code&gt;default:shortcode_attr&lt;/code&gt; (my hidden fields weren't filled out to begin with because I forgot this).&lt;/p&gt;

&lt;p&gt;Also remember to implement the &lt;code&gt;shortcode_atts_wpcf7&lt;/code&gt; filter as described in the Contact Form 7 instructions 🙂&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing it all
&lt;/h2&gt;

&lt;p&gt;That's it. Uploaded to production and now my users can (and do) report errors, so I get emails like this one I just submitted myself.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--i4LHUD3M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f0390m2lpcdqv7zy49lg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i4LHUD3M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f0390m2lpcdqv7zy49lg.png" alt="Image description" width="593" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The from field at the top would be filled out if I had writing anything in the form's email field. Since I did not, the field is empty.&lt;/p&gt;

&lt;p&gt;Notice the link directly to the product from where the form was submitted. Easy to add to the email with the '[_url]' parameter in Contact Form 7. Like this on the form's mail tab:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--M7_xHQtB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x7wp2wo2p2s22k54zev6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--M7_xHQtB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x7wp2wo2p2s22k54zev6.png" alt="Image description" width="685" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>flatsome</category>
      <category>popup</category>
      <category>ux</category>
    </item>
    <item>
      <title>How to Build a Model Train Calculator the Right Way</title>
      <dc:creator>Mads Phikamphon</dc:creator>
      <pubDate>Fri, 26 Aug 2022 02:02:42 +0000</pubDate>
      <link>https://dev.to/genvejen/how-to-build-a-model-train-calculator-the-right-way-48o3</link>
      <guid>https://dev.to/genvejen/how-to-build-a-model-train-calculator-the-right-way-48o3</guid>
      <description>&lt;p&gt;If you are into model trains like me (I run the website &lt;a href="https://www.modelprices.com/"&gt;Model Prices&lt;/a&gt;), you will know that things quickly become expensive. Much more expensive than you might expect when you start out.&lt;/p&gt;

&lt;p&gt;To avoid such bad surprises, I decided to make a model train layout cost calculator. A calculator where you can enter various factors like layout dimensions, scale, number of locomotives etc. and get a rough estimate of how much your new layout is going to cost you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gathering requirements
&lt;/h2&gt;

&lt;p&gt;I looked around, but couldn't find any existing model train layout cost calculators. All I could find were some blog posts talking about the costs and giving very different estimates of the cost. Some would say $30 per sq.ft. while others would say $100+ per square feet.&lt;/p&gt;

&lt;p&gt;Having no clear consensus on costs and thinking like a pro developer, I decided to gather requirements before I started programming my new calculator.&lt;/p&gt;

&lt;p&gt;In a few Facebook groups for model trains, I wrote about my planned calculator and asked what people thought about the factors and numbers I planned to use. Two of these posts got 20+ comments, which made me quite sure there was a need for such a calculator - and it also gave me a lot of input on how I should design the calculator.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--A110_OxR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2eyow96v88rw9399wynj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A110_OxR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2eyow96v88rw9399wynj.png" alt="Image description" width="631" height="727"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Javascript part
&lt;/h2&gt;

&lt;p&gt;Having gathered the requirements, I knew what I had to make and could start the actual programming (i.e. start the best part). Most of the calculator was written in Javascript, while the actual cost calculation was done by calling an API function.&lt;/p&gt;

&lt;p&gt;Writing the calculator in Javascript meant that it was easy to do validations before the numbers were submitted to the API and the Javascript could also take of currency conversions (which is important since my website targets people in multiple countries).&lt;/p&gt;

&lt;p&gt;One of the validations the Javascript do is to validate that the total of the 3 environment percentages below is always 100%. The Javascript also updates how many percentages are missing if the total is below 100%.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OELXTKJE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qb35qm81ukmh65n504q5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OELXTKJE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qb35qm81ukmh65n504q5.png" alt="Image description" width="800" height="108"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The API cost calculation
&lt;/h2&gt;

&lt;p&gt;The actual cost calculation could easily have been done by Javascript too, but instead, I choose to let it be done by an API function. There are two reasons for that:&lt;/p&gt;

&lt;p&gt;When the cost calculation is done by an API function, I can store the entered data in a database table, so I can see how people are using the calculator - and later on, when lots of people have used it, I can maybe write a blog post based on layout statistics (how many locomotives and wagons are people using for different sizes of layouts, what are the most popular layout sizes for different model scales, etc.)&lt;/p&gt;

&lt;p&gt;Using the database table, I can also assign each calculation a unique id. With the id, people can share their calculations and/or tweak their calculation later on.&lt;/p&gt;

&lt;p&gt;Since my website is running on WordPress, the calculation function has been written as an extension to the WordPress REST API. Nice, easy and no need to setup a lot of things to get the API running. All I needed to do was to create an API class with my function in and add to the action 'rest_api_init'.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wiVNE9Lg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ia8i0fvfuu1rkdaczn0z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wiVNE9Lg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ia8i0fvfuu1rkdaczn0z.png" alt="Image description" width="501" height="126"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The id
&lt;/h2&gt;

&lt;p&gt;As mentioned above, I assign each calculation a unique id. This is done by the calculation function, so when the function returns the results to the user, he can see a link with his id in.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9y_VFWzs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nuigmx63q706v13b8dcf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9y_VFWzs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nuigmx63q706v13b8dcf.png" alt="Image description" width="769" height="246"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using a bit of Javascript, the current url is also changed to include the id.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ve-VvrIk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fuiiweqabvkwtjrv6g6o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ve-VvrIk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fuiiweqabvkwtjrv6g6o.png" alt="Image description" width="738" height="74"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;To make sure everything is working correctly, I did a bunch of testing myself. But as most developers know, you are often blind to your own mistakes and might unconsciously avoid the dangerous parts of your code when testing.&lt;/p&gt;

&lt;p&gt;I therefore also asked some friends to test things a bit, so I could be sure everything was working before starting marketing my calculator.&lt;/p&gt;

&lt;p&gt;If you want to, you can also &lt;a href="https://www.modelprices.com/layout-cost-calculator/"&gt;check out the finished calculator here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sharing it
&lt;/h2&gt;

&lt;p&gt;The calculator is done, but unless you are coding something for your own personal use, code isn't worth much without anyone using it. It was therefore time to start spreading the word a bit.&lt;/p&gt;

&lt;p&gt;Luckily I had already mentioned my calculator plans in some Facebook groups when I was gathering requirements. So why not return to those groups and share the finished calculator?&lt;/p&gt;

&lt;p&gt;That way I could show people that I have actually implemented the thing we discussed - and hopefully, some of these people would check out the calculator, find it so useful and start using it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DFouY_rQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x2pdh10o1fwtccl8ojty.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DFouY_rQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x2pdh10o1fwtccl8ojty.png" alt="Image description" width="622" height="581"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Chart JS scatter diagram with 2 datasets</title>
      <dc:creator>Mads Phikamphon</dc:creator>
      <pubDate>Mon, 30 May 2022 06:37:03 +0000</pubDate>
      <link>https://dev.to/genvejen/chart-js-scatter-diagram-with-2-datasets-5g06</link>
      <guid>https://dev.to/genvejen/chart-js-scatter-diagram-with-2-datasets-5g06</guid>
      <description>&lt;p&gt;On my site &lt;a href="https://www.flaskepriser.dk/"&gt;Flaskepriser&lt;/a&gt;, I had some issues creating a &lt;a href="https://www.chartjs.org/"&gt;Chart JS&lt;/a&gt; scatter diagram with 2 datasets.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why use 2 datasets&lt;/strong&gt;&lt;br&gt;
First of all, let's look at why you might need to have more than one dataset in your scatter diagram. If you have only one dataset, your points in the diagram will all be the same color/size.&lt;/p&gt;

&lt;p&gt;That didn't work for me, as I needed to have points in two different colors. My site is comparing wine and I needed one color for the wine being compared and another colors for the wines I'm comparing with. Like this where I'm comparing &lt;a href="https://www.flaskepriser.dk/p/f1dfd9a8/"&gt;this wine&lt;/a&gt; vs. other wines:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DnTwp9is--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/owky6gz4m8pg1ssv8gch.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DnTwp9is--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/owky6gz4m8pg1ssv8gch.png" alt="Image description" width="698" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JSON datasets&lt;/strong&gt;&lt;br&gt;
My site is based on Wordpress, so I use PHP to build the JS necessary to make Chart JS work and display my scatter diagram.&lt;/p&gt;

&lt;p&gt;Having two datasets in the JSON that Chart JS use is quite easy. Just put the JSON together like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ynwZ1X7q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ans53wdym277ovjgoc7z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ynwZ1X7q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ans53wdym277ovjgoc7z.png" alt="Image description" width="710" height="197"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, each dataset has a &lt;em&gt;pointRadius&lt;/em&gt; property which determine the size of the points (both datasets above have the same point sizes). Each dataset also has a &lt;em&gt;backgroundColor&lt;/em&gt; property which controls the color of the points (the datasets above have different colors, so the points will end up having different colors in the scatter diagram).&lt;/p&gt;

&lt;p&gt;Also note the &lt;em&gt;order&lt;/em&gt; property that determines the order that the points are drawn. Smart if you have points that end up on top of each other. The lower the order, the later the points are drawn (so the order 1 points in the JSON above are drawn after the order 2 points, and the order 1 points thereby end up on top of the order 2 points).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Labels&lt;/strong&gt;&lt;br&gt;
One slightly annoying thing is that the datasets don't have their own list of labels. Instead they share the same list of labels 😅&lt;/p&gt;

&lt;p&gt;First I thought the order of the datasets determined how the labels would be used, but I couldn't make it work and get the points from both datasets get the right labels.&lt;/p&gt;

&lt;p&gt;Luckily, there was a simple workaround. First the list of labels are used by the dataset being drawn first. That means the labels are used by the order 2 dataset, since the lower the order, the later the points are drawn.&lt;/p&gt;

&lt;p&gt;One would then think that it would then be possible to just add elements to the list of labels and then these extra elements would be used by the next dataset, but it didn't seem to work that way.&lt;/p&gt;

&lt;p&gt;So to get the proper labels for the second dataset, I wrote a quick event listener that would be called when the page has been loaded:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DheN3gdd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z1x6gxxoul4x44arcf5n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DheN3gdd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z1x6gxxoul4x44arcf5n.png" alt="Image description" width="636" height="53"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This little function sets the label of the element in the second dataset and all the points thereby end up having the correct labels (my second dataset only has one element).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VKh4DRw_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/shmxfqjxc88loseulb3h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VKh4DRw_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/shmxfqjxc88loseulb3h.png" alt="Image description" width="703" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Point links&lt;/strong&gt;&lt;br&gt;
When people click the points in my scatter diagrams, they are sent to the pages of other wines.&lt;/p&gt;

&lt;p&gt;Clickable points is not a standard function in Chart JS, but thanks to &lt;a href="https://stackoverflow.com/questions/30899664/how-to-add-links-to-chart-js-doughnut-charts"&gt;Stack Overflow&lt;/a&gt;, there was a quick solution to make the points clickable:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZSG3fZoK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ejs0px1u15hi8l2tvr0b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZSG3fZoK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ejs0px1u15hi8l2tvr0b.png" alt="Image description" width="492" height="84"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>chartjs</category>
      <category>diagram</category>
    </item>
    <item>
      <title>How to use paper.js to compare RC cars</title>
      <dc:creator>Mads Phikamphon</dc:creator>
      <pubDate>Tue, 07 Sep 2021 13:55:01 +0000</pubDate>
      <link>https://dev.to/genvejen/how-to-use-paper-js-to-compare-rc-cars-576c</link>
      <guid>https://dev.to/genvejen/how-to-use-paper-js-to-compare-rc-cars-576c</guid>
      <description>&lt;p&gt;On my site &lt;a href="https://www.rcdonkey.com/"&gt;RC Donkey&lt;/a&gt; we compare radio controlled cars 💥 One of the many specs we compare is the dimensions of the cars, so people for example can compare car lengths, heights, etc.&lt;/p&gt;

&lt;p&gt;These dimensions are of course numbers, for example one car might have a length of "320 mm" while another car might have a length of "360 mm". Comparing numbers like that is difficult for us humans, so we decided to make diagrams that let people compare the dimensions in a better way.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ppgQD3mQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xswz0owg3nftf3o6pia4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ppgQD3mQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xswz0owg3nftf3o6pia4.png" alt="Sideview diagram of two RC cars" width="659" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tech choices
&lt;/h2&gt;

&lt;p&gt;At first we thought about generating the diagrams as images through PHP (RC Donkey is based on a modified Wordpress installation, so PHP is used heavily on the site). Considering we have hundreds of cars in our database and people can compare them in any way they want, it quickly became clear that we would end up with way too many images. The image generating idea was therefore dropped.&lt;/p&gt;

&lt;p&gt;Luckily image generation wasn't the only option available. Another option was to generate the diagrams through Javascript.&lt;/p&gt;

&lt;p&gt;Writing custom JS code for generating diagrams can quickly become a bit complicated, but luckily there are several diagramming libraries available. We ended up using &lt;a href="http://paperjs.org/"&gt;paper.js&lt;/a&gt; and it turned out to be a great choice. It's easy to use and works really well for generating the diagrams we need.&lt;/p&gt;

&lt;p&gt;Let's take a look at how we generate the diagram above that compares the dimensions of two cars seen from above (the two cars shown is &lt;a href="https://www.rcdonkey.com/products/trx90076-4/"&gt;the Traxxas HOSS&lt;/a&gt; and &lt;a href="https://www.rcdonkey.com/products/trx89076-4/"&gt;the Traxxas Maxx&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RFifKx9C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/16rv75z2r0hgni61z9fm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RFifKx9C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/16rv75z2r0hgni61z9fm.png" alt="Seen from above diagram" width="662" height="511"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the diagram
&lt;/h2&gt;

&lt;p&gt;All the car specs are in a database, so we start out by generating a JSON object containing the dimensions of the cars. The JSON object also contains various data like the names of the cars, so we can also add a legend to the diagram etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qsGlC7Ld--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v67kwtgxxheb00ga5syb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qsGlC7Ld--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v67kwtgxxheb00ga5syb.png" alt="The JSON object containing diagram data for the two cars" width="580" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We then call a JS function that parses the JSON and builds the diagram. This function first check that the JSON is valid, for example that it actually contains some car dimensions. The function then setup the canvas that we will use to contain the diagram.&lt;/p&gt;

&lt;p&gt;We have set the diagram to have a certain max. width depending on the device. So for desktop the max. width is 700px while it is max. 400px for mobile devices. The function therefore starts with determining the max. length of the cars. The max. length is compared with the diagram width. If the max. width is bigger, we set a multiplier to a number &amp;lt; 0 to make sure no car ends up being bigger than the diagram. If the max. width is smaller, the multiplier is set to a number &amp;gt; 0 to make the biggest car match the width of the diagram.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--faxiLPD---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aa08s2lyptkwwnxkbz12.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--faxiLPD---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aa08s2lyptkwwnxkbz12.png" alt="Calculating the multiplier" width="607" height="177"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the multiplier has been set, the function loops through the cars in the JSON and converts the dimensions into rectangles. This is quite simple to do with paper.js:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2GwWCE_j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/31no3yx6mhwme5eecgds.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2GwWCE_j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/31no3yx6mhwme5eecgds.png" alt="Drawing a rectangle with paper.js" width="609" height="62"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice how the multiplier is used to make sure the dimensions are modified to match the width of the diagram.&lt;/p&gt;

&lt;p&gt;In the same loop, we also generate each car's part of the legend. Again something that is quite simple to do with paper.js. After all, the legend is just about generating some text:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DziEh7Cq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s4mrf0xc7hvee0301tvx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DziEh7Cq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s4mrf0xc7hvee0301tvx.png" alt="Writing text with paper.js" width="561" height="97"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The scale
&lt;/h2&gt;

&lt;p&gt;Finally, we use paper.js to generate the scale to the right side of the diagram. To make the scale have the right intervals, we use the max. width of the cars. The highest point on the scale simply matches the max. width of the cars since the diagram shows the cars seen from above. If the cars were seen from the side, the highest point on the scale should simply match the max. height of the cars instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Diagram done
&lt;/h2&gt;

&lt;p&gt;So that's it. The diagram is now done and people can check it out when they visit our site. You can &lt;a href="https://www.rcdonkey.com/compare/?vehicles=6,5"&gt;check it out here&lt;/a&gt;, together with some other diagrams for the same car comparison.&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
    <item>
      <title>How We Created a Simple Avatar Generator for Our Fitness Site</title>
      <dc:creator>Mads Phikamphon</dc:creator>
      <pubDate>Fri, 14 Feb 2020 15:52:11 +0000</pubDate>
      <link>https://dev.to/genvejen/how-we-created-a-simple-avatar-generator-for-our-fitness-site-4eg0</link>
      <guid>https://dev.to/genvejen/how-we-created-a-simple-avatar-generator-for-our-fitness-site-4eg0</guid>
      <description>&lt;p&gt;Having interviewed more than 200 fitness pros on &lt;a href="https://www.bulkhackers.com/"&gt;our site&lt;/a&gt;, we decided that we needed a way to get more traffic to our interviews.&lt;/p&gt;

&lt;p&gt;Traffic that everybody would benefit from: Us for getting a more popular site and the people we interview for getting a bigger audience 💥💥&lt;/p&gt;

&lt;p&gt;Instagram is a big thing in fitness, so one of our traffic strategies is to increase our Instagram presence (which to be honest is a bit sad at the moment).&lt;/p&gt;

&lt;p&gt;To increase our Instagram audience, we needed to stand out and not be like all the other fitness accounts on Instagram. In other words, we could not just be another account with people working out in some gym.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to stand out
&lt;/h2&gt;

&lt;p&gt;To stand out, we decided to focus on making a personalized avatar for every single person we interview.&lt;/p&gt;

&lt;p&gt;Using avatars instead of photos on our Instagram would let us stand out - and we would also not have to worry about people complaining about us misusing their photos.&lt;/p&gt;

&lt;p&gt;Now, we could then have moved on and drawn all the avatars manually, but that would create a potential bottleneck in our workflow (since none of us are that good at drawing) + doing things manually would hurt my programmer heart 😀&lt;/p&gt;

&lt;p&gt;So instead of doing things manually, we decided to make an avatar generator!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DE53GdID--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/savrxllslhyzmld2xckv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DE53GdID--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/savrxllslhyzmld2xckv.png" alt="Our finished avatar generator" width="800" height="577"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An avatar generator that will not only be useful for fitness. It will also be useful for other interests, so we for example can have an avatar generator for &lt;a href="https://www.madlisten.dk/"&gt;our food site&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to make an avatar generator
&lt;/h2&gt;

&lt;p&gt;Thinking things through, we estimated that it wouldn't be that difficult to make the generator - and at the end, it turned out that our estimate was correct. It wasn't that difficult.&lt;/p&gt;

&lt;p&gt;Actually, the most difficult (i.e. time-consuming) part was to get all the shapes drawn, but more about that later.&lt;/p&gt;

&lt;p&gt;Essentially, our avatar generator works by layering shapes on top of each other using the JavaScript NPM &lt;a href="https://www.npmjs.com/package/merge-images"&gt;merge-images&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EYF_yAG6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/qhdr0r79xskai9hewn2l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EYF_yAG6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/qhdr0r79xskai9hewn2l.png" alt="Alt Text" width="800" height="249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The layered images can then be downloaded as a .png - and voila, then you have your own personalized avatar that is ready for Instagram (it's even square size, 600 x 600 px, so you don't need to worry about cropping)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--L34vzbaV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/cxj0tk6ojzlpsxznfzco.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--L34vzbaV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/cxj0tk6ojzlpsxznfzco.png" alt="Alt Text" width="600" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What about the colors
&lt;/h2&gt;

&lt;p&gt;Considering we have ~150 different shapes, you might wonder if everything had to been drawn manually.&lt;/p&gt;

&lt;p&gt;The answer is yes and no.&lt;/p&gt;

&lt;p&gt;All the shapes have been manually drawn in 3 grey colors to begin with. A main color grey, a dark grey and a light grey.&lt;/p&gt;

&lt;p&gt;Drawing ~150 shapes manually takes a lot of time, so that's why the drawing was the most time-consuming part of the project (together with the code being relatively simple).&lt;/p&gt;

&lt;p&gt;Luckily we didn't have to do the coloring manually. Thanks to all the shapes being the same three colors, we could write some PHP code that took care of the shape coloring.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nUja_PPt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/evwp478ox3mv2c5jxw5q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nUja_PPt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/evwp478ox3mv2c5jxw5q.png" alt="Alt Text" width="800" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The way this works is that our code checks if all the colored versions of each shape exists. If a color doesn't exist, the code will take care of replacing the 3 grey colors with 3 colors in another, predefined color.&lt;/p&gt;

&lt;p&gt;Judging from the awesome subreddit &lt;a href="http://reddit.com/r/programmerhumor"&gt;Programmer Humour&lt;/a&gt;, many people hate PHP.&lt;/p&gt;

&lt;p&gt;To be honest, I'm quite alright with PHP - and we had to choose PHP because our site is a Wordpress site under the hood and our avatar generator is a Wordpress plugin (Wordpress is mostly written in PHP).&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting ready of Instagram
&lt;/h2&gt;

&lt;p&gt;Now, we don't want the avatars on &lt;a href="https://www.instagram.com/bulkhackers/"&gt;our Instagram&lt;/a&gt; to look exactly like the ones you can download from our generator.&lt;/p&gt;

&lt;p&gt;We want to them to be even nicer, so we run the finished avatars through some more code.&lt;/p&gt;

&lt;p&gt;When an avatar has been generated, we put it through a bit more PHP magic that crops the avatar in a hexagon shape and adds the name of the person being interviewed + the title of the interview.&lt;/p&gt;

&lt;p&gt;After that piece of magic, the avatar is ready for being shared on Instagram.&lt;/p&gt;

&lt;p&gt;The actual posting to Instagram could be manual, but being programmers we of our course let things run automatically through the Buffer API 👍&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking forward
&lt;/h2&gt;

&lt;p&gt;The first version of &lt;a href="https://www.bulkhackers.com/avatar/"&gt;our avatar generator&lt;/a&gt; is done and we use it almost every day to generate new avatars, but things doesn't stop there.&lt;/p&gt;

&lt;p&gt;Being big fans of continuous improvement, we plan to keep building and expanding the generator.&lt;/p&gt;

&lt;p&gt;Soon, we should be able to add functions for changing the hair if you had a hat or other headgear, adding more accessories and of course having more shapes to choose from (especially if we decide to cover other interests like for example food and cooking).&lt;/p&gt;

</description>
      <category>php</category>
      <category>javascript</category>
      <category>socialmedia</category>
      <category>avatar</category>
    </item>
  </channel>
</rss>
