<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Naguel]]></title><description><![CDATA[I'm Nahuel, and these are my work experiences, ideas and thoughts as a web developer working on the eCommerce industry.]]></description><link>https://naguel.com/</link><image><url>https://naguel.com/favicon.png</url><title>Naguel</title><link>https://naguel.com/</link></image><generator>Ghost 6.44</generator><lastBuildDate>Tue, 09 Jun 2026 08:02:34 GMT</lastBuildDate><atom:link href="https://naguel.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Prepare your self-evaluation before your performance review]]></title><description><![CDATA[This is an opportunity to not only get feedback from your company, but also to help shape your role into it, defining a roadmap for your own career. When you are not part of this conversation, when you are just a listener, you leave your future in the company up to whatever other decides for you.]]></description><link>https://naguel.com/prepare-your-self-evaluation-before-your-performance-review/</link><guid isPermaLink="false">60b2e59bff0c35003edfebed</guid><category><![CDATA[Work experiences]]></category><dc:creator><![CDATA[Nahuel Sanchez]]></dc:creator><pubDate>Thu, 21 Oct 2021 19:58:00 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1434030216411-0b793f4b4173?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDF8fGNvZmZlZSUyMHJldmlld3xlbnwwfHx8fDE2MjI0MDQ1NDU&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1434030216411-0b793f4b4173?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDF8fGNvZmZlZSUyMHJldmlld3xlbnwwfHx8fDE2MjI0MDQ1NDU&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" alt="Prepare your self-evaluation before your performance review"><p>Don&apos;t we love having a good performance review, from our bosses to ourselves, every now and then? Of course we do! Is that moment were we get to be told how great of an employee we have been (finger cross that&apos;s the case) and to potentially get a salary raise (and I don&apos;t have to ask how much we love that).</p><p>Thing is that our performance review, appraisal, catch up, or whatever you would like to call, it is about having a conversation where you should also bring something to the table.</p><h2 id="why">Why?</h2><p>This is an opportunity to not only get feedback from your company, but also to help shape your role into it, to define a roadmap for your own career for the next cycle up to, let&apos;s say, your next performance review.</p><p>When you are not part of this conversation, when you are just a listener, you leave your future in the company up to whatever other decides for you. If you are &quot;sort of lucky&quot;, the company you work for might already has defined a plan for you, and if you are &quot;very lucky&quot; you will like that plan. You would be betting, twice.</p><p>But, again, that&apos;s oddly the case when we don&apos;t have a say for our career.</p><h2 id="how">How?</h2><p>What I like to do for basically all meetings I have (and my performance review is no exception) is come prepare with notes and bullet points to discuss.</p><p>For this particular scenario I recommend doing a self-evaluation, ahead of the meeting, to know were we stand and were we would like to go from there.</p><p>Depending on our role in the company we can also cover where the company stands, where we would like it to go, and how we think we can get there.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://naguel.com/average-is-officially-over-so-dont-be-that-at-work/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Average is officially over, so don&#x2019;t be that at work</div><div class="kg-bookmark-description">There was a time when you would learn a skill and that would be enough to succeed, but nowadays what you learn has an expire date as much as the milk in your refrigerator.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://naguel.com/favicon.png" alt="Prepare your self-evaluation before your performance review"><span class="kg-bookmark-author">Naguel</span><span class="kg-bookmark-publisher">Nahuel Sanchez</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://images.unsplash.com/photo-1506962522065-cf1bed0da013?ixlib=rb-1.2.1&amp;q=80&amp;fm=jpg&amp;crop=entropy&amp;cs=tinysrgb&amp;w=2000&amp;fit=max&amp;ixid=eyJhcHBfaWQiOjExNzczfQ" alt="Prepare your self-evaluation before your performance review"></div></a></figure><p>I divide my self-evaluation, self-assessment, auto-evaluation, or, again, whatever you would like to call it, into different sections starting with &quot;<strong>What I like to do and what I don&apos;t like to do</strong>&quot;.</p><p>This is a reflection time opportunity for me to know, up to this moment, after everything I went through from the last catch up, of all the things I&apos;ve been doing so far what I actually like to do, and if I think I would like to continue doing them.</p><p>For example, let&apos;s say I&apos;ve been doing a lot of documentation since the last time we had a catch up. Did I like that? Or was it more of an emergency role I had to take on that I would like to dodge from now on? Can I think of any available role I might like to fulfill with this skill that I think I&apos;m good at and also like to perform?</p><p>The &quot;what I don&apos;t like to do&quot; part is to identify if the tasks I&apos;ve been performing were those sort of a one-time-only tasks due to an emergency, or if they are in fact part of my job description.</p><p>If the stuff you don&apos;t like to do outnumber the things you do like, then you have a bigger problem here. But that&apos;s just another good idea for doing a self-evaluation: you can get yourself aware of how happy (or not) you are at your job.</p><p>The second section is called &quot;<strong>Things I should put more attention at</strong>&quot;, which basically means &quot;what I&apos;ve been doing wrong&quot; (but let&apos;s keep a positive tone here and not sound that radical). Now is when I need to be truly honest with myself in order to be able to identify where I have room to improve at work.</p><p>It&apos;s not only about telling where I could be better, but also to discover why I wasn&apos;t doing my best so far, and what I think could increase my performance on these areas.</p><p>I consider important to demonstrate that I&apos;m able to tell when I&apos;m not at my best before somebody points that out to me, and that I&apos;m also capable of being part of &quot;fixing&quot; this situation with ideas and suggestions of my own.</p><p>Third section is about &quot;<strong>Things we should keep an eye on</strong>&quot;, which involves the company itself and it&apos;s my chance to talk about how I see the place I work in.</p><p>You are, supposedly, at a different position than your superiors, therefore you might be able to provide another vision at how things are: what do you think the company is doing well, what things would be good to avoid losing, and what things do you think the company should put more effort in.</p><p>Clearly, this would be attached to your bosses&apos; willingness to get some feedback on a meeting designed mainly to provide it to you. But, if you have the chance to give it a shot, just go for it.</p><p>Since my role is more technical I do have a fourth-ish section which is more like a twist for the last one, and I call it &quot;<strong>Things we should keep an eye on... from a technical point of view</strong>&quot; (the title speaks for itself).</p><p>This is my opportunity to say where I would like things to go, for the company, on the technical side, which is allegedly my area of expertise.</p><p>Following on the example of me doing a lot of documentation, I can bring ideas on how we can make this behaviour part of the company&apos;s culture.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/2021/05/prepare-your-self-evaluation-before-your-performance-review-01.png" class="kg-image" alt="Prepare your self-evaluation before your performance review" loading="lazy" width="1642" height="1518" srcset="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w600/2021/05/prepare-your-self-evaluation-before-your-performance-review-01.png 600w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w1000/2021/05/prepare-your-self-evaluation-before-your-performance-review-01.png 1000w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w1600/2021/05/prepare-your-self-evaluation-before-your-performance-review-01.png 1600w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/2021/05/prepare-your-self-evaluation-before-your-performance-review-01.png 1642w" sizes="(min-width: 1200px) 1200px"></figure><p>Up there you can see a real self-evaluation I did on March 2019 before a performance review I had, and two more on the sidebar.</p><p>Keeping them works as a log to retrace my steps when I feel overwhelmed to assess if I&apos;m on track regarding my latest self-evaluation of my performance or if I need to adjust something.</p><p>Basically, my idea is to avoid working blindly from one catch up to the other.</p>]]></content:encoded></item><item><title><![CDATA[Certificate verify failed with Composer and MAMP]]></title><description><![CDATA[Fixing this is quite simple as it only involves replacing the cacert.pem file with the one you can download here.]]></description><link>https://naguel.com/error-14090086-ssl-routines-ssl3_get_server_certificate-certificate-verify-failed/</link><guid isPermaLink="false">61996a1f47cfae003ba47bf7</guid><category><![CDATA[Composer]]></category><category><![CDATA[MAMP]]></category><dc:creator><![CDATA[Nahuel Sanchez]]></dc:creator><pubDate>Mon, 13 Sep 2021 22:13:00 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1456406644174-8ddd4cd52a06?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDI5fHxjb2ZmZWUlMjBzdHJlc3N8ZW58MHx8fHwxNjM3NDQ2NzI1&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1456406644174-8ddd4cd52a06?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDI5fHxjb2ZmZWUlMjBzdHJlc3N8ZW58MHx8fHwxNjM3NDQ2NzI1&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" alt="Certificate verify failed with Composer and MAMP"><p>I&apos;m going to be honest with you: I have no idea why this can happen.</p><p>This is one of those errors that makes you say &quot;<em>this started to happen out of the sudden and I&apos;m 100% sure I touched nothing</em>&quot;. But it&apos;s there, and I have a potential solution, hoping you are in a hurry to get it fixed without asking too much questions.</p><pre><code class="language-bash">[Composer\Downloader\TransportException]
The &quot;https://example:example@repo.example.com/packages.json&quot; file could not be downloaded: SSL operation failed with code 1. OpenSSL Error messages:
error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed
Failed to enable crypto
failed to open stream: operation failed</code></pre><p>The full error is up there and it appears when you use Composer such as when running <code>composer install</code>, and it seems to be that your computer is using a wrong (or not up to date?) CA certificate when trying to communicate with a Composer repository.</p><blockquote>cacert.pem is a bundle of CA certificates that you use to verify that the server is really the correct site you&apos;re talking to (when it presents its certificate in the SSL handshake).<br><br><a href="https://stackoverflow.com/a/14988132?ref=naguel.com">Comment by Daniel Stenberg on Stack Overflow</a></blockquote><p>So, fixing this is quite simple as it only involves replacing the <code>cacert.pem</code> file with the one you can download here: <a href="https://curl.se/docs/caextract.html?ref=naguel.com">CA certificates extracted from Mozilla</a>.</p><p>If you are using MAMP, chance are that the file you need to replace, locally, is on <code>/Applications/MAMP/Library/OpenSSL/certs/</code>, but if you are unsure you can open a Terminal and run <code>locate cacert.pem</code> to get a list of all the places where you can find the Certificate Authority file.</p><p>If still unsure about the location of the <code>cacert.pem</code> you need to replace, check your <code>php.ini</code> and look for the <code>openssl.cafile=</code> line.</p><pre><code class="language-bash">[openssl]
; The location of a Certificate Authority (CA) file on the local filesystem
; to use when verifying the identity of SSL/TLS peers. Most users should
; not specify a value for this directive as PHP will attempt to use the
; OS-managed cert stores in its absence. If specified, this value may still
; be overridden on a per-stream basis via the &quot;cafile&quot; SSL stream context
; option.
openssl.cafile=path/to/cacert.pem</code></pre><p>Finally, remember to restart Apache before trying again.</p>]]></content:encoded></item><item><title><![CDATA[Migrate a Magento project from any server to Cloudways]]></title><description><![CDATA[A complete guide with everything you need to know to successfully migrate any Magento project living on any server to Cloudways.]]></description><link>https://naguel.com/migrate-a-magento-project-from-any-server-to-cloudways/</link><guid isPermaLink="false">60c3fcd60aad29003ee587e5</guid><category><![CDATA[Magento]]></category><category><![CDATA[Magento 2]]></category><category><![CDATA[Cloudways]]></category><category><![CDATA[DevOps]]></category><dc:creator><![CDATA[Nahuel Sanchez]]></dc:creator><pubDate>Thu, 19 Aug 2021 22:27:00 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1547105484-2871e57056f8?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDMwfHxjb2ZmZWUlMjBjb21wdXRlcnxlbnwwfHx8fDE2MjM1MzY0NjI&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1547105484-2871e57056f8?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDMwfHxjb2ZmZWUlMjBjb21wdXRlcnxlbnwwfHx8fDE2MjM1MzY0NjI&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" alt="Migrate a Magento project from any server to Cloudways"><p>While the title up there make this post looks like a promoted and/or paid one, that&apos;s not the case (I wish), and instead this is an honest appreciation of Cloudways and how it has made my life easy while dealing with servers, specially considering that I don&apos;t think myself as an advanced devOps.</p><p>Recently at the company I work for we had the task to move an existing Magento project, already in production and publicly accessible, from a server outside Cloudways to a server managed by Cloudways.</p><p>What&apos;s next is going to be long, and everything described could take around 3 days (one day for the server creation, another day for testing the new instance, and a third day for the actual site moving), depending on your skills.</p><p>So let&apos;s get to it.</p><h2 id="preparation">Preparation</h2><p>Make sure to tick a few boxes before moving forward by checking if you have the following:</p><ul><li>Credentials to access the original server over SSH and SFTP, with enough permissions to manipulate files within the web root folder (usually <code>public_html</code> or <code>www</code>), use <code>scp</code>, <code>tar</code>, and <code>cat</code> for server configuration files such as the one for Nginx and Varnish.</li><li>Server permissions to use <code>mysqldump</code> to create a database backup, or a way to get your hands on a database backup of the project living on the original server.</li><li>Access or a point of contact for managing DNS changes for the project&#x2019;s domain.</li><li>Access to the payment gateway accounts and/or credentials needed to configure the payment methods.</li></ul><p>Finally, make sure to identify which third-party services currently connect directly to the server over SFTP or similar, because those will need to be reconfigured to point to the new IP and/or to be given new SFTP credentials.</p><h2 id="create-the-server-in-cloudways">Create the server in Cloudways</h2><p>Decide on the server size and create it on Cloudways, making sure to factor in how much space you will need for the database, files, and &quot;maneuver&quot; as you will be moving zipped files from the original server to unzip them later.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/2021/06/migrate-a-magento-project-from-any-server-to-cloudways-01-1.png" class="kg-image" alt="Migrate a Magento project from any server to Cloudways" loading="lazy" width="1901" height="1126" srcset="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w600/2021/06/migrate-a-magento-project-from-any-server-to-cloudways-01-1.png 600w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w1000/2021/06/migrate-a-magento-project-from-any-server-to-cloudways-01-1.png 1000w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w1600/2021/06/migrate-a-magento-project-from-any-server-to-cloudways-01-1.png 1600w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/2021/06/migrate-a-magento-project-from-any-server-to-cloudways-01-1.png 1901w" sizes="(min-width: 1200px) 1200px"><figcaption>Server creation example using a &quot;PHP - Custom App&quot; for a Magento Open Source 2.2</figcaption></figure><p>Cloudways offers Magento-ready instances for specific versions. If the project you are moving uses a Magento version already listed in Cloudways you can select this version from the dropdown that appears when creating the server, otherwise make sure to select &#x201C;<em>PHP - Custom App</em>&#x201D; instead.</p><p>This is important because, for example, if you are moving a Magento 2.2 version to Cloudways you can not select &#x201C;<em>Magento - Version 2.4.1 (with Elasticsearch)</em>&#x201D; from the dropdown as this instance will come with Elasticsearch 7 out of the box and you won&#x2019;t be able to downgrade it to Elasticsearch 6 (which is the required version for Magento 2.2 using ElasticSuite).</p><p>If you need to go down the route of selecting &#x201C;<em>PHP - Custom App</em>&#x201D;, then you must contact Cloudways Support for them to &quot;flag&quot; this instance as Magento internally, after creating it.</p><p>This is because Cloudways offers specific configurations and performance-oriented settings for each type of instance, like an internal logic in place to load the specific Varnish settings a Magento project would require.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/2021/06/migrate-a-magento-project-from-any-server-to-cloudways-02-1.png" class="kg-image" alt="Migrate a Magento project from any server to Cloudways" loading="lazy" width="2000" height="1211" srcset="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w600/2021/06/migrate-a-magento-project-from-any-server-to-cloudways-02-1.png 600w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w1000/2021/06/migrate-a-magento-project-from-any-server-to-cloudways-02-1.png 1000w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w1600/2021/06/migrate-a-magento-project-from-any-server-to-cloudways-02-1.png 1600w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w2400/2021/06/migrate-a-magento-project-from-any-server-to-cloudways-02-1.png 2400w" sizes="(min-width: 1200px) 1200px"><figcaption>Cloudways Support flagging a &quot;PHP - CustomApp&quot; as Magento internally</figcaption></figure><p>Whatever the Application type you choose, you still need to contact Cloudways Support to ask them to:</p><ul><li>Downgrade Composer from version 2 to 1 by running <code>composer self-update --1</code> (you can&apos;t do it because you don&apos;t have enough server permissions to do so).</li><li>Install a few Elasticseach plugins by running <code>bin/elasticsearch-plugin install analysis-phonetic; bin/elasticsearch-plugin install analysis-icu; bin/elasticsearch-plugin install analysis-smartcn;</code> on the <code>/usr/share/elasticsearch</code> folder (another thing you won&apos;t be able to do due to permissions).</li></ul><p>You still need to configure a few bits here and there using the Cloudways Dashboard to make sure you match your project needs, including but not limited to the following items:</p><ul><li>PHP version, execution limit, memory limit, error reporting, and timezone.</li><li>MySQL version and timezone.</li><li>Nginx WAF module to be Cloudflare, Sucuri or disabled.</li><li>Elasticsearch version, if needed.</li><li>Redis, if needed.</li><li>Varnish, if needed.</li></ul><p>I can&apos;t tell what you need to put in those fields as that depends on the project.</p><h2 id="configure-the-application">Configure the Application</h2><p>Inside the &quot;<em>Domain Management</em>&quot; section, make sure to configure the project&apos;s domain and all the additional necessary domains (like the ones used for different stores if your Magento project is configured to use multiple websites and stores).</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/2021/06/migrate-a-magento-project-from-any-server-to-cloudways-03-1.png" class="kg-image" alt="Migrate a Magento project from any server to Cloudways" loading="lazy" width="1901" height="1127" srcset="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w600/2021/06/migrate-a-magento-project-from-any-server-to-cloudways-03-1.png 600w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w1000/2021/06/migrate-a-magento-project-from-any-server-to-cloudways-03-1.png 1000w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w1600/2021/06/migrate-a-magento-project-from-any-server-to-cloudways-03-1.png 1600w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/2021/06/migrate-a-magento-project-from-any-server-to-cloudways-03-1.png 1901w" sizes="(min-width: 1200px) 1200px"><figcaption>&quot;<em>Domain Management</em>&quot; configuration inside &quot;<em>Application Management</em>&quot;</figcaption></figure><p>Your &quot;<em>SSL Certificate</em>&quot; configuration will depend on what your project needs.</p><p>Since you are moving from one server to other, chances are you already have a SSL certificate that you can use, otherwise the Let&apos;s Encrypt option is quite good.</p><p>If you are using a firewall such as Cloudflare or Sucuri, the certificate might be &quot;living there&quot; already so there&apos;s nothing you need to configure here.</p><p>Do not add any cron in the &quot;<em>Cron Job Management</em>&quot; section for now.</p><p>We&apos;ll come back to the &quot;<em>Application Management</em>&quot; configuration later at the end.</p><h2 id="stop-crons-on-the-original-server">Stop crons on the original server</h2><p>By editing the crontab with <code>crontab -e</code> on the original server, or by contacting the original server hosting provider, disable all the crons by adding <code>#</code> at the beginning of each line.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/2021/06/migrate-a-magento-project-from-any-server-to-cloudways-03.png" class="kg-image" alt="Migrate a Magento project from any server to Cloudways" loading="lazy" width="2000" height="1276" srcset="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w600/2021/06/migrate-a-magento-project-from-any-server-to-cloudways-03.png 600w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w1000/2021/06/migrate-a-magento-project-from-any-server-to-cloudways-03.png 1000w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w1600/2021/06/migrate-a-magento-project-from-any-server-to-cloudways-03.png 1600w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/2021/06/migrate-a-magento-project-from-any-server-to-cloudways-03.png 2148w" sizes="(min-width: 1200px) 1200px"><figcaption>An example of editing the crons with crontab -e and commenting out every line</figcaption></figure><p>This needs to happen before you move any file from the original server to Cloudways, and before the database backup creation.</p><p>Technically speaking, you want to avoid Magento to keep on writing any file in, for example, the <code>var</code> folder within the Magento root folder, related to Orders processing or Catalog management (like stock updates), and you want Magento to stop altering tables related also to those entities, which are the usual stuff affected by crons (among many other things).</p><p>If, for example, there are pending Order and/or Catalog tasks, they will be taking place in Cloudways after we finish the migration and we enable back the crons on the new server.</p><h2 id="move-the-files">Move the files</h2><p>Make sure to move the <code>pub/media</code> folder from within the Magento root folder, and any other custom folder and file that doesn&apos;t live in the repository.</p><p>Usually, there are some custom folders and files inside the <code>pub</code> and <code>var</code> folders that are not created automatically.</p><p>If you happen to be using Capistrano on the original server you would have a <code>shared</code> folder in the web root. In that case, just move that folder from the original server to Cloudways.</p><p>The way I do it is by creating a <code>.tar.gz</code> file with everything in it, but any cache folder...</p><figure class="kg-card kg-code-card"><pre><code class="language-shell">[user_original]:~$ tar cvzfh shared.tar.gz shared/ --exclude=&apos;pub/media/catalog/product/cache&apos;;</code></pre><figcaption>tar cvzfh filename.tar.gz folder-to-zip/ --exclude=&apos;path/to/exclude&apos;;</figcaption></figure><p>...and then I transfer it from the original server to Cloudways using <code>scp</code>...</p><figure class="kg-card kg-code-card"><pre><code class="language-shell">[user_original]:~$ scp shared.tar.gz user_cloudways@18.133.133.133:/mnt/data/home/master/applications/example/public_html</code></pre><figcaption>scp filename.tar.gz dest_username@123.dest.ip.123:/path/where/to/transfer</figcaption></figure><p>Make sure to push this file into the <code>public_html</code> folder in the Cloudways server, so you just need to unzip it there with <code>tar -xvf shared.tar.gz;</code> and then delete it.</p><p>Something I would like to do, just in case, after this big move, is to fix any potential permissions issue with the files and folders I just unzipped, by reseting those permissions using the Cloudways Dashboard.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/2021/06/migrate-a-magento-project-from-any-server-to-cloudways-05-1.png" class="kg-image" alt="Migrate a Magento project from any server to Cloudways" loading="lazy" width="1901" height="1517" srcset="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w600/2021/06/migrate-a-magento-project-from-any-server-to-cloudways-05-1.png 600w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w1000/2021/06/migrate-a-magento-project-from-any-server-to-cloudways-05-1.png 1000w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w1600/2021/06/migrate-a-magento-project-from-any-server-to-cloudways-05-1.png 1600w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/2021/06/migrate-a-magento-project-from-any-server-to-cloudways-05-1.png 1901w" sizes="(min-width: 1200px) 1200px"><figcaption>Application Management setting to reset files/folder permissions</figcaption></figure><h2 id="enable-maintenance-mode">Enable Maintenance Mode</h2><p>Put the site living on the original server into Maintenance Mode by running <code>bin/magento maintenance:enable</code> before proceeding. </p><p>For what it&apos;s worth, the downtime starts now.</p><h2 id="move-the-database">Move the database</h2><p>Using <code>mysqldump</code> create a database backup on the original server.</p><pre><code class="language-shell">[user_original]:~$ mysqldump -uroot -p database_name &gt; database_export.sql;</code></pre><p>For security reasons, make sure this happens on a folder not accessible over the browser, like on the <code>private_html</code> folder or anywhere outside the web root.</p><p>Once done, push this <code>.sql</code> file to the Cloudways server using <code>scp</code> again.</p><figure class="kg-card kg-code-card"><pre><code class="language-shell">[user_original]:~$ scp database_export.sql user_cloudways@18.133.133.133:/mnt/data/home/master/applications/example/private_html</code></pre><figcaption><em>scp filename.sql dest_username@123.dest.ip.123:/path/where/to/transfer</em></figcaption></figure><p>For the same security reasons, make sure to push this file to the <code>private_html</code> folder in the Cloudways server.</p><p>Once the transfer is completed, and before anything else, you need to remove the <code>DEFINER</code> from the <code>.sql</code> backup to avoid any &quot;<em>Access denied; you need (at least one of) the SUPER privilege(s) for this operation</em>&quot; issue while trying to import it.</p><p>Basically, run the following command on the <code>private_html</code> folder in Cloudways (or anywhere you pushed the <code>.sql</code> file before).</p><pre><code class="language-shell">[user_cloudways]:~$ sed &apos;s/\sDEFINER=`[^`]*`@`[^`]*`//g&apos; -i database_export.sql;</code></pre><p>Now the backup is ready to be imported into the actual database in the new server.</p><p>For this to happen you need to contact Cloudways Support with the request.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/2021/06/migrate-a-magento-project-from-any-server-to-cloudways-04.png" class="kg-image" alt="Migrate a Magento project from any server to Cloudways" loading="lazy" width="2000" height="1211" srcset="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w600/2021/06/migrate-a-magento-project-from-any-server-to-cloudways-04.png 600w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w1000/2021/06/migrate-a-magento-project-from-any-server-to-cloudways-04.png 1000w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w1600/2021/06/migrate-a-magento-project-from-any-server-to-cloudways-04.png 1600w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w2400/2021/06/migrate-a-magento-project-from-any-server-to-cloudways-04.png 2400w" sizes="(min-width: 1200px) 1200px"><figcaption>Cloudways Support handling the database import</figcaption></figure><p>After the import, make sure to delete the <code>.sql</code> file.</p><h2 id="configure-magento">Configure Magento</h2><p>By accessing directly to the recently imported database in Cloudways, and not through the Magento Admin Panel, make sure to have the correct details for Varnish and Elasticsearch, keeping in mind that Cloudways uses port <code>8081</code> for Varnish, and <code>127.0.0.1:9200</code> for Elasticsearch.</p><p>Make sure there&apos;s no reference in the <code>core_config_data</code> table to the IP for the old server that you might need to change for the IP of the new one.</p><p>Go back to the files, and edit the <code>app/etc/env.php</code> file you transferred from the original server to fix the credentials for connecting to the new database living in Cloudways now.</p><p>In that same file, correct the details for Redis (if used) keeping in mind that Cloudways uses <code>127.0.0.1</code> and <code>6379</code> for the host and port, respectively.</p><p>Once done, clear cache and reindex to make sure everything is working.</p><h2 id="configure-the-application-again">Configure the Application again</h2><p>Go back to the &quot;<em>Application Management</em>&quot; in the Cloudways Dashboard and configure, in the new server, all the crons you commented out on the original server, making sure to use the right paths for the new server.</p><p>Inside the &quot;<em>Application Settings</em>&quot;, configure the &quot;<em>WEBROOT</em>&quot; to point to the <code>pub</code> folder from within the Magento root folder.</p><h2 id="point-the-domain-to-the-new-server">Point the domain to the new server</h2><p>First thing first, make sure Magento is still on Maintenance Mode on the new server, and whitelist your IP to be able to access the site (using the <code>bin/magento maintenance:allow-ips</code> command).</p><p>Now change the DNS settings to point the project&apos;s domain to the new server.</p><p>The whole idea is to open the site only for you in order to test it before allowing real customers. So, while the DNS change propagates, some customers will hit the site on the old server (that will show the maintenance page forever and ever), and others will hit the site on the new Cloudways server (that it will also show the maintenance page while you test it).</p><p>Now is when you test the site and make sure everything is okay.</p><h2 id="disable-maintenance-mode">Disable Maintenance Mode</h2><p>Once you are done with the testing open the site, now in Cloudways, to the public, by disabling the Maintenance Mode (with the <code>bin/magento maintenance:disable</code> command).</p><p>The downtime ends now.</p>]]></content:encoded></item><item><title><![CDATA[Magento and FORBIDDEN/12/index read-only / allow delete (api)]]></title><description><![CDATA[If you are unlucky enough to be reading this article it means that you are seeing that error when trying to reindex Magento.

This happens because you are probably running out of disk space and Elasticsearch turns itself into read only mode because, well, there's no more space to do stuff.]]></description><link>https://naguel.com/blocked-by-forbidden-12-index-read-only-allow-delete-api/</link><guid isPermaLink="false">613d4a458bc5db003e0be9b5</guid><category><![CDATA[Elasticsearch]]></category><category><![CDATA[Magento]]></category><category><![CDATA[Magento 2]]></category><dc:creator><![CDATA[Nahuel Sanchez]]></dc:creator><pubDate>Thu, 22 Jul 2021 14:54:00 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1581574313687-c8b70fcd663a?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDE2fHxjb2ZmZWUlMjBicmVha3xlbnwwfHx8fDE2MzE0MDg1MTQ&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1581574313687-c8b70fcd663a?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDE2fHxjb2ZmZWUlMjBicmVha3xlbnwwfHx8fDE2MzE0MDg1MTQ&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" alt="Magento and FORBIDDEN/12/index read-only / allow delete (api)"><p>If you are unlucky enough to be reading this article it means that you are seeing that error when trying to reindex Magento.</p><pre><code class="language-bash">ElasticSuite Category Indexing index process unknown error:
{&quot;error&quot;:{&quot;root_cause&quot;:[{&quot;type&quot;:&quot;cluster_block_exception&quot;,&quot;reason&quot;:&quot;blocked by: [FORBIDDEN/12/index read-only / allow delete (api)];&quot;}],&quot;type&quot;:&quot;cluster_block_exception&quot;,&quot;reason&quot;:&quot;blocked by: [FORBIDDEN/12/index read-only / allow delete (api)];&quot;},&quot;status&quot;:403}
ElasticSuite Thesaurus Indexing index process unknown error:
{&quot;error&quot;:{&quot;root_cause&quot;:[{&quot;type&quot;:&quot;cluster_block_exception&quot;,&quot;reason&quot;:&quot;blocked by: [FORBIDDEN/12/index read-only / allow delete (api)];&quot;}],&quot;type&quot;:&quot;cluster_block_exception&quot;,&quot;reason&quot;:&quot;blocked by: [FORBIDDEN/12/index read-only / allow delete (api)];&quot;},&quot;status&quot;:403}</code></pre><p>This happens because you are probably running out of disk space and Elasticsearch turns itself into read only mode because, well, there&apos;s no more space to do stuff.</p><p>In order to get out of this situation, you need to first disable that Elasticsearch feature of switching to read only mode (otherwise it will happen again) by running the following...</p><pre><code class="language-bash">curl -XPUT -H &quot;Content-Type: application/json&quot; http://localhost:9200/_cluster/settings -d &apos;{&quot;persistent&quot;:{&quot;cluster.routing.allocation.disk.threshold_enabled&quot;:false}}&apos;</code></pre><p>...and then get Elasticsearch out of the read only mode with the next command:</p><pre><code class="language-bash">curl -XPUT -H &quot;Content-Type: application/json&quot; http://localhost:9200/_all/_settings -d &apos;{&quot;index.blocks.read_only_allow_delete&quot;: null}&apos;</code></pre><p>Besides this, you&apos;ll need to do some disk clean up to recover some space.</p>]]></content:encoded></item><item><title><![CDATA[Missing query string parameters when using Varnish on Magento]]></title><description><![CDATA[I had a simple task that consisted on getting some query string parameters from the URL, from the PHP $_GET variable, to store them in Magento.

What sounded like a very straightforward task got complicated because the $_GET variable was missing some of the those parameters I needed to save.]]></description><link>https://naguel.com/missing-query-string-parameters-when-using-varnish-on-magento/</link><guid isPermaLink="false">60b2b697ff0c35003edfeb01</guid><category><![CDATA[Magento]]></category><category><![CDATA[Magento 2]]></category><category><![CDATA[PHP]]></category><category><![CDATA[Varnish]]></category><category><![CDATA[Rakuten]]></category><dc:creator><![CDATA[Nahuel Sanchez]]></dc:creator><pubDate>Wed, 09 Jun 2021 00:52:00 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1598908314833-809d7bb6c2c6?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDUzfHxlbXB0eSUyMGNvZmZlZXxlbnwwfHx8fDE2MjIzMzU4NTM&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1598908314833-809d7bb6c2c6?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDUzfHxlbXB0eSUyMGNvZmZlZXxlbnwwfHx8fDE2MjIzMzU4NTM&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" alt="Missing query string parameters when using Varnish on Magento"><p>I had this weird issue a time ago with a simple task that consisted on getting some query string parameters from the URL, from the PHP <code>$_GET</code> variable, to store them in Magento after the Customer places the Order.</p><p>What sounded like a very straightforward task got complicated because the <code>$_GET</code> variable was missing some of the those parameters I needed to save.</p><p>Debugging this issue made me realise that all the missing parameters where those starting with <code>utm</code>. I was literally going to this example URL...</p><pre><code>http://example.com/test.php?utm_source=Source&amp;utm_medium=Medium&amp;utm_content=Content&amp;utm_term=Term&amp;siteId=42689&amp;siteName=naguel.com</code></pre><p> ...to get the following incomplete output when printing the <code>$_GET</code> variable:</p><figure class="kg-card kg-image-card"><img src="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/2021/05/missing-query-string-parameters-when-using-varnish-on-magento-01.png" class="kg-image" alt="Missing query string parameters when using Varnish on Magento" loading="lazy" width="1578" height="974" srcset="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w600/2021/05/missing-query-string-parameters-when-using-varnish-on-magento-01.png 600w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w1000/2021/05/missing-query-string-parameters-when-using-varnish-on-magento-01.png 1000w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/2021/05/missing-query-string-parameters-when-using-varnish-on-magento-01.png 1578w" sizes="(min-width: 720px) 720px"></figure><p>The cause of this issue was Varnish&apos;s recommended VCL configuration for Magento that includes the following inside the <code>sub vcl_recv {}</code>.</p><pre><code class="language-vcl"># Remove all marketing get parameters to minimize the cache objects
    if (req.url ~ &quot;(\?|&amp;)(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+|_bta_[a-z]+)=&quot;) {
        set req.url = regsuball(req.url, &quot;(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+|_bta_[a-z]+)=[-_A-z0-9+()%.]+&amp;?&quot;, &quot;&quot;);
        set req.url = regsub(req.url, &quot;[?|&amp;]+$&quot;, &quot;&quot;);
}</code></pre><p>That was literally subtracting all marketing-related <code>GET</code> parameters from the URL, including those starting with <code>utm_</code>.</p><p>The solution is quite simple: remove the <code>utm_[a-z]+</code> from the <code>if</code> conditional and restart Varnish to apply the changes.</p><h3 id="utm-parameters">UTM parameters?</h3><p>UTM stands for &quot;Urchin Tracking Module&quot; (who cares, right?), which are basically marketing-related parameters to track marketing campaigns, and to know how people interact with the site.</p><p>In my case I was dealing with them because of a <a href="https://www.rakuten.com/?ref=naguel.com">Rakuten</a> integration with Magento.</p><p>More information on what they are and what we can do with them can be found on &quot;<a href="https://neilpatel.com/blog/the-ultimate-guide-to-using-utm-parameters/?ref=naguel.com">The Ultimate Guide to Using UTM Parameters</a>&quot; post from <a href="https://neilpatel.com/blog/?ref=naguel.com">Neil Patel&apos;s blog</a>.</p>]]></content:encoded></item><item><title><![CDATA[A few soft skills interview questions to get to know the candidate]]></title><description><![CDATA[For interviews to fill a technical role it's obvious that the questions needs to be technicals.

But soft skills related questions allow you to get to know the human you are interviewing, having in mind that you'll share with that person more than some lines of code if you ended up offering the job.]]></description><link>https://naguel.com/a-few-soft-skills-interview-questions-to-get-to-know-the-candidate/</link><guid isPermaLink="false">5fd4100f872a2b0039d7a55c</guid><category><![CDATA[Job Interviews]]></category><dc:creator><![CDATA[Nahuel Sanchez]]></dc:creator><pubDate>Sat, 17 Apr 2021 03:10:00 GMT</pubDate><media:content url="https://images.unsplash.com/1/bag-and-hands.jpg?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MXwxMTc3M3wwfDF8c2VhcmNofDQ2fHxjb2ZmZWUlMjBtZWV0aW5nfGVufDB8fHw&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/1/bag-and-hands.jpg?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MXwxMTc3M3wwfDF8c2VhcmNofDQ2fHxjb2ZmZWUlMjBtZWV0aW5nfGVufDB8fHw&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" alt="A few soft skills interview questions to get to know the candidate"><p>For job interviews to fill a technical role it&apos;s obvious that the questions needs to be, well, technicals, with focus on the hard skills questions aiming to know the candidate&apos;s knowledge in a specific framework, code language, software, etcetera.</p><p>But the attitude is very very very... very much... important. I said it before:</p><blockquote>Everybody has access to the same documentation, to the same in-house training programs, to the same software, to everybody&apos;s code, to basically the same people to ask questions and to learn from... and what&apos;s set the difference between someone progressing in his or her line of work and someone stuck is the personality each developer has.</blockquote><p>Soft skills related questions allow you to get to know the human you are interviewing, having in mind that you&apos;ll share with that person more than some lines of code if you ended up offering the job.</p><p>It also humanise the interview. If you pay attention people are usually tense answering the technical questions but when you throw in a soft skills one candidates relax and enjoy the conversation created around that question.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://naguel.com/developers-work-success-being-too-much-about-personality-rather-than-hard-skills/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Developer&#x2019;s work success being too much about personality rather than hard skills</div><div class="kg-bookmark-description">Maybe what&#x2019;s set the difference between someone progressing in his or her line of work and someone stuck is the personality each developer has.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://naguel.com/favicon.png" alt="A few soft skills interview questions to get to know the candidate"><span class="kg-bookmark-author">Naguel</span><span class="kg-bookmark-publisher">Nahuel Sanchez</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://images.unsplash.com/photo-1543269865-4430f94492b9?ixlib=rb-1.2.1&amp;q=80&amp;fm=jpg&amp;crop=entropy&amp;cs=tinysrgb&amp;w=2000&amp;fit=max&amp;ixid=eyJhcHBfaWQiOjExNzczfQ" alt="A few soft skills interview questions to get to know the candidate"></div></a></figure><p>At my current job we have a few very good soft skills questions I would like to share now in case you find them useful (our interviews are for web developers so the questions, while soft skills related questions, orbit around that role).</p><h3 id="what-do-you-think-makes-a-good-developer">What do you think makes a good developer?</h3><p>I personally expect whatever answer that&apos;s not about code, software, or any other hard skill stuff.</p><p>People usually talks about the ability of being flexible, passionate about it, the importance on working as part of a team, etcetera. Still some candidates mention hard skill stuff not covered before in the interview such as testing, and that&apos;s fine.</p><h3 id="what-do-you-think-makes-a-good-manager">What do you think makes a good manager?</h3><p>I like this one because it&apos;s a chance for the candidate to talk about others, and it&apos;s expected that they think of their current boss (obviously).</p><p>The answer will give you an idea of how the candidate works on a team structure where somebody is on a position above them. And at the same time it will hint you if the candidate will do well with the current managers at your company.</p><p>I like the answers about leadership and motivation.</p><h3 id="what-do-you-think-you-would-add-to-the-team-if-you-were-to-get-the-job">What do you think you would add to the team if you were to get the job?</h3><p>This is the polite version of &quot;<em>Why do you want this job besides money?</em>&quot;.</p><p>I like this one because it forces the candidate to summarise what&apos;s their contribution to the team. And it&apos;s important to emphasise the team in the question, like you are not just adding something to the company but adding something to a team made of real humans.</p><h3 id="what-would-you-expect-from-the-team-if-you-were-to-get-the-job">What would you expect from the team if you were to get the job?</h3><p>In opposition to the previous one, this is the time for the candidate to tell us how they see themselves after any period of time as part of a new team.</p><p>Again, we are asking about the team, not the company, so we try to keep it human while guiding the candidate into giving us something not technical.</p><h3 id="if-you-were-to-organise-a-work-social-night-out-what-would-you-plan">If you were to organise a work social night out, what would you plan?</h3><p>This always takes the candidates by surprise. They are thinking about PHP, VueJS, code reviews, pull requests and out the sudden they need to think about beers (because beers is the right answer to a social night out plan).</p><h3 id="what-do-you-like-to-do-when-you-aren-t-coding">What do you like to do when you aren&apos;t coding?</h3><p>There&apos;s no better question than this one to force the candidate to stop talking about hard skills and say something about their personal life (as much as they want, don&apos;t force people into talking about their personal life on a job interview).</p><p>It is also fun to learn about others people hobbies.</p>]]></content:encoded></item><item><title><![CDATA[Proper way to configure asynchronous email sending in Magento]]></title><description><![CDATA[Magento recommends to configure this to be async for performance, so the email dispatch process doesn't block nor delay what the customer is doing, or to avoid long cron runs when an ERP is updating orders status.

I also recommended to configure this to be async to avoid having unsent emails.]]></description><link>https://naguel.com/proper-way-to-configure-asynchronous-email-sending-in-magento/</link><guid isPermaLink="false">5fc2ccc8e872a900394e6681</guid><category><![CDATA[Magento]]></category><category><![CDATA[Magento 2]]></category><category><![CDATA[Performance]]></category><dc:creator><![CDATA[Nahuel Sanchez]]></dc:creator><pubDate>Tue, 16 Mar 2021 01:39:00 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1556808752-77f2fe75360b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MXwxMTc3M3wwfDF8c2VhcmNofDI5fHx8ZW58MHx8fA&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1556808752-77f2fe75360b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MXwxMTc3M3wwfDF8c2VhcmNofDI5fHx8ZW58MHx8fA&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" alt="Proper way to configure asynchronous email sending in Magento"><p>There are two ways to configure how Magento send order related emails (order confirmation, invoice, shipment and credit memo emails):</p><ul><li>Either immediately when an action is performed (for example, right after you place an order).</li><li>Or cron-based (asynchronous).</li></ul><p>Magento itself recommends to configure this to be asynchronous for performance reasons, so the email dispatch process doesn&apos;t block nor delay what the customer is doing (for example, less time consumption when the customer is placing an order), or to avoid long cron runs (or total crons block) when an ERP is updating orders status in bulk.</p><blockquote>Enabling the &#x201C;Asynchronous email notifications&#x201D; setting moves processes that handle checkout and order processing email notifications to the background.<br><br><a href="https://devdocs.magento.com/guides/v2.4/performance-best-practices/configuration.html?ref=naguel.com">Configuration best practices</a> by Magento</blockquote><p>For my personal experience, it is also recommended to configure emails sending to be asynchronous to avoid having unsent emails.</p><p>When this is configured as immediately (not async), if an email fails to be dispatched because of any reason (like a server timeout) then Magento won&#x2019;t try to send that email again in the future and the customer won&#x2019;t be ever notified of his/her action.</p><p>Basically, there are a lot of good reasons to have this to be async.</p><h2 id="before-setting-this-up">Before setting this up</h2><p>If you are going live for the first time on a new site there&apos;s not much to worry about, but if you are changing this setting from not-async to cron-based on an already live site then there&apos;s something to consider first.</p><p>The way this works when it&apos;s configured to be async is that Magento will rely on a cron to pick up from the database (from those tables related to Orders, Invoices, Shipments and Credit Memos) all those entities where the email was not dispatched, and it will send it.</p><p>Problem is that Magento doesn&apos;t care much about the date of those entities.</p><p>For example, if there&#x2019;s an Order from 2019 whose order confirmation email was not sent because of any reason (for example, because there was a PHP error that stopped the execution), the cron will now pick this Order up and Magento will send the email related to that order.</p><p>To avoid this behaviour we should mark all pending emails from Orders, Invoices, Shipments, and Credit Memos as if they doesn&apos;t need to be dispatched, which can be done by executing the following SQL statements before enabling the asynchronous sending.</p><pre><code class="language-sql">UPDATE sales_order SET send_email = 0;
UPDATE sales_invoice SET send_email = 0;
UPDATE sales_shipment SET send_email = 0;
UPDATE sales_creditmemo	 SET send_email = 0;</code></pre><p>What we are doing here is ignoring the sending of emails for old Orders (and Invoices, Shipments and Credit Memos) so when we change this to be async the cron will only cares for future stuff.</p><h2 id="changing-the-configuration">Changing the configuration</h2><p>Enable the &#x201C;<em>Asynchronous sending</em>&#x201D; option under &#x201C;<em>Stores &#x2192; Settings &#x2192; All Stores &#x2192; Sales &#x2192; Sales Email &#x2192; General Settings</em>&#x201D;.</p>]]></content:encoded></item><item><title><![CDATA[Unable to load dynamic library 'pgsql.so']]></title><description><![CDATA[This issue seems to be related to macOS Big Sur and MAMP (somehow) and it can be easily solved by fixing some broken symlinks.]]></description><link>https://naguel.com/unable-to-load-dynamic-library-pgsql-so/</link><guid isPermaLink="false">5fd36594872a2b0039d7a4b7</guid><category><![CDATA[MAMP]]></category><category><![CDATA[PHP]]></category><dc:creator><![CDATA[Nahuel Sanchez]]></dc:creator><pubDate>Thu, 11 Feb 2021 01:39:00 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1546202515-3e08809182cf?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MXwxMTc3M3wwfDF8c2VhcmNofDI0fHxjb2ZmZWUlMjBsb3N0fGVufDB8fHw&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1546202515-3e08809182cf?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MXwxMTc3M3wwfDF8c2VhcmNofDI0fHxjb2ZmZWUlMjBsb3N0fGVufDB8fHw&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" alt="Unable to load dynamic library &apos;pgsql.so&apos;"><p>I had this weird issue that seems to be related to macOS Big Sur and MAMP, allegedly, either both combined or when upgrading any of those two (or both?).</p><p>I don&apos;t know exactly why this happened to me out of the sudden (I blame MAMP as it was the last thing that I updated) but I managed to fix it anyway.</p><pre><code>PHP Warning:  PHP Startup: Unable to load dynamic library &apos;pgsql.so&apos; (tried: /Applications/MAMP/bin/php/php7.3.21/lib/php/extensions/no-debug-non-zts-20180731/pgsql.so (dlopen(/Applications/MAMP/bin/php/php7.3.21/lib/php/extensions/no-debug-non-zts-20180731/pgsql.so, 9): Library not loaded: /Applications/MAMP/Library/pg/lib/libpq.5.dylib
  Referenced from: /Applications/MAMP/bin/php/php7.3.21/lib/php/extensions/no-debug-non-zts-20180731/pgsql.so
  Reason: image not found), /Applications/MAMP/bin/php/php7.3.21/lib/php/extensions/no-debug-non-zts-20180731/pgsql.so.so (dlopen(/Applications/MAMP/bin/php/php7.3.21/lib/php/extensions/no-debug-non-zts-20180731/pgsql.so.so, 9): image not found)) in Unknown on line 0</code></pre><p>To get around this situation, many suggest to update Brew with <code>brew update</code>. That didn&apos;t work for me (and to be honest I can&apos;t see what&apos;s the relationship with Brew and MAMP) but you can give it a try anyway since it&apos;s easy to do.</p><p>What&apos;s interesting about the error above is that it mentions <code>pgsql.so.so</code> which is clearly wrong because of the double <code>.so</code> extension.</p><h2 id="so-how-do-i-actually-fix-this-issue">So how do I actually fix this issue?</h2><p>Go to that <code>extensions</code> subfolder mentioned in the error (for example, mine is <code>/Applications/MAMP/bin/php/php7.3.21/lib/php/extensions/no-debug-non-zts-20180731/</code>) and create a symlink for <code>pdo_pgsql.so</code> called <code>pdo_pgsql.so.so</code> by doing:</p><pre><code class="language-shell">ln -s pdo_pgsql.so pdo_pgsql.so.so</code></pre><p>Now it doesn&apos;t matter what MAMP is looking for as it will find it either way.</p><p>That&apos;s not all. Go to <code>/Applications/MAMP/Library/pg/lib</code> and you&apos;ll notice something really weird which are broken paths for the symlinks <code>libpq.5.dylib</code> and <code>libpq.dylib</code> as seen below.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/2020/12/unable-to-load-dynamic-library-pgsql-so-01.png" class="kg-image" alt="Unable to load dynamic library &apos;pgsql.so&apos;" loading="lazy" width="2000" height="635" srcset="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w600/2020/12/unable-to-load-dynamic-library-pgsql-so-01.png 600w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w1000/2020/12/unable-to-load-dynamic-library-pgsql-so-01.png 1000w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w1600/2020/12/unable-to-load-dynamic-library-pgsql-so-01.png 1600w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/2020/12/unable-to-load-dynamic-library-pgsql-so-01.png 2218w" sizes="(min-width: 1200px) 1200px"></figure><p>Again, how that happened is another mystery. But it doesn&apos;t matter, let&apos;s just fix those symlinks by deleting them and creating them again.</p><pre><code>ln -s libpq.5.7.dylib libpq.5.dylib;
ln -s libpq.5.7.dylib libpq.dylib;</code></pre><p>As you can see on the previous screenshot, the symlink <code>libpq.5.dylib</code> points to a broken path for <code>libpq.5.7.dylib</code> which is basically right there on the same folder. The same goes for <code>libpq.dylib</code>.</p><p>At the end everything should look like the following:</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/2020/12/unable-to-load-dynamic-library-pgsql-so-02.png" class="kg-image" alt="Unable to load dynamic library &apos;pgsql.so&apos;" loading="lazy" width="2000" height="696" srcset="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w600/2020/12/unable-to-load-dynamic-library-pgsql-so-02.png 600w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w1000/2020/12/unable-to-load-dynamic-library-pgsql-so-02.png 1000w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w1600/2020/12/unable-to-load-dynamic-library-pgsql-so-02.png 1600w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/2020/12/unable-to-load-dynamic-library-pgsql-so-02.png 2218w" sizes="(min-width: 1200px) 1200px"></figure>]]></content:encoded></item><item><title><![CDATA[Magento and a deadlock found when trying to get lock]]></title><description><![CDATA[Basically, when you have no way to "unlock" an index, and after you already tried the reset and manual reindex, just change the prefix in your app/etc/env.php file to something new, and try to reindex again.]]></description><link>https://naguel.com/magento-and-a-deadlock-found-when-trying-to-get-lock/</link><guid isPermaLink="false">5fda0867e8f2c900393d14f1</guid><category><![CDATA[Magento]]></category><category><![CDATA[Magento 2]]></category><dc:creator><![CDATA[Nahuel Sanchez]]></dc:creator><pubDate>Sat, 09 Jan 2021 23:33:00 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1554304480-a75ebf32ebb4?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MXwxMTc3M3wwfDF8c2VhcmNofDN8fGNvZmZlZSUyMGxvY2t8ZW58MHx8fA&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1554304480-a75ebf32ebb4?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MXwxMTc3M3wwfDF8c2VhcmNofDN8fGNvZmZlZSUyMGxvY2t8ZW58MHx8fA&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" alt="Magento and a deadlock found when trying to get lock"><p>&quot;What now?&quot; issues every now and then with Magento are the norm, and I got this one a few days ago:</p><pre><code class="language-bash">SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction, query was: INSERT INTO `catalog_product_index_eav_temp` SELECT DISTINCT [...]</code></pre><p>Apparently the server went down for a second, or MySQL went down... or something happened and a reindex process was interrupted (in my case the one for the &quot;Product EAV&quot; index), and there was no way to make it work again.</p><p>Even the usual <code>bin/magento indexer:reset</code> and then a manual reindex with <code>bin/magento indexer:reindex</code> didn&apos;t do the trick and the only difference was that instead of the previous error I was getting the classic one:</p><pre><code class="language-bash">Product EAV index is locked by another reindex process. Skipping.</code></pre><p>Lucky me, I find <a href="https://twitter.com/willemwigman/status/1177162364308860928?ref=naguel.com">this tweet by @willemwigman</a> on Twitter that basically indicates that, when you have no way to &quot;unlock&quot; an index and after you already tried the reset and manual reindex, spot the <code>lock</code> node within your <code>app/etc/env.php</code> file and change the <code>prefix</code> within the inner <code>config</code> node.</p><pre><code class="language-php">&lt;?php
return [
    [...]
    &apos;lock&apos; =&gt; [
        &apos;provider&apos; =&gt; &apos;db&apos;,
        &apos;config&apos; =&gt; [
            &apos;prefix&apos; =&gt; &apos;new-prefix-here&apos;
        ]
    ]
];</code></pre><p>Reset the indexes and try to reindex again.</p><p>That alone should do the trick.</p>]]></content:encoded></item><item><title><![CDATA[Add related posts to Ghost blog]]></title><description><![CDATA[The related posts are quite easy to add to Ghost if you have some basic knowledge on how to edit your current theme (there's no option to turning this ON and OFF on the Admin, unfortunately, so you must do it on the theme itself).]]></description><link>https://naguel.com/add-related-posts-to-ghost-blog/</link><guid isPermaLink="false">5a85782a259b5700181e4c6e</guid><category><![CDATA[Ghost]]></category><category><![CDATA[Blogging]]></category><dc:creator><![CDATA[Nahuel Sanchez]]></dc:creator><pubDate>Tue, 22 Dec 2020 03:18:00 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1509339338943-fc6da78cdd4b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MXwxMTc3M3wwfDF8c2VhcmNofDl8fGlwYWQlMjBjb2ZmZWV8ZW58MHx8fA&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1509339338943-fc6da78cdd4b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MXwxMTc3M3wwfDF8c2VhcmNofDl8fGlwYWQlMjBjb2ZmZWV8ZW58MHx8fA&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" alt="Add related posts to Ghost blog"><p>The related posts are quite easy to add to <a href="https://ghost.org/?ref=naguel.com">Ghost</a> if you have some basic knowledge on how to edit your current theme (there&apos;s no option to turning this ON and OFF on the Admin, unfortunately, so you must do it on the theme itself).</p><p>If you open your theme&apos;s files you would see a <code>post.hbs</code> template which is the one for the articles (for &quot;this page you are seeing right now&quot;, basically), and the block expression <code>{{#post}}...{{/post}}</code> would be the one containing everything related to the post itself.</p><p>Outside that expression, after it, we want to add the related posts taking advantage of the <code>{{#get}}</code> helper.</p><blockquote><code>{{#get}}</code> is a special block helper that makes a custom query to the Ghost API to fetch publicly available data.<br><br><a href="https://ghost.org/docs/api/v3/handlebars-themes/helpers/get/?ref=naguel.com">get documentation for Functional Helpers by Ghost</a></blockquote><p>Clearly, you can use this helper to get the related posts anywhere you want, like on the sidebar of the blog if yours have one, or in a page instead of a post (but I personally like them at the end of an article).</p><p>Let&apos;s say you would like to get <strong>a list of related posts based on the tags of the current one</strong>, which can be done by filtering the data on the <code>filter</code> attribute.</p><pre><code class="language-mustache">{{#get &quot;posts&quot; filter=&quot;tags:[{{post.tags}}]+id:-{{post.id}}&quot; as |related|}}
	[...]
{{/get}}</code></pre><p>In this case the <code>filter</code> attribute also contains <code>id:-{{post.id}}</code> to ignore, from the list of posts we are getting, the current article (we wouldn&apos;t want to suggest as related post the same post the user just read).</p><p>You can add as many filters as you want using the <code>+</code> sign as separator.</p><p>Inside this helper, the <code>related</code> &quot;object&quot; will be the one containing all the related post, so you just need to &quot;loop it&quot;.</p><pre><code class="language-mustache">{{#get &quot;posts&quot; filter=&quot;tags:[{{post.tags}}]+id:-{{post.id}}&quot; as |related|}}
    &lt;div class=&quot;related-posts-wrapper&quot;&gt;
        {{#foreach related}}
            &lt;article class=&quot;{{post_class}}&quot;&gt;
                &lt;a href=&quot;{{url}}&quot;&gt;{{title}}&lt;/a&gt;
            &lt;/article&gt;
        {{/foreach}}
    &lt;/div&gt;
{{/get}}</code></pre><p>Once inside the <code>foreach</code> you are in the context of the post, and then you can just get whatever you want from that post such as the <code>{{url}}</code>, <code>{{title}</code>, etcetera.</p><p>You can limit how many post to show by using the <code>limit</code> attribute on the <code>{{#get}}</code> helper (15 by default, which seems like too much)</p><pre><code class="language-mustache">{{#get &quot;posts&quot; limit=&quot;2&quot; filter=&quot;tags:[{{post.tags}}]+id:-{{post.id}}&quot; as |related|}}
    ...
{{/get}}</code></pre><p>The related posts can be anything you like and you would like to consider as related posts, as you are not limited to that filter for the tags I used as an example.</p><p>I&apos;m currently using <code>tags:[{{post.primary_tag.slug}}]</code> within the filters to <strong>only consider those posts that have the primary tag of the current post as a tag</strong> in any position, as I think those posts would be more relevant to the current one.</p><pre><code class="language-mustache">{{#get &quot;posts&quot; filter=&quot;tags:[{{post.primary_tag.slug}}]+id:-{{post.id}}&quot; as |related|}}
    ...
{{/get}}</code></pre><p>This is not the same as using <code>primary_tag:{{post.primary_tag.slug}}</code> which is another filter option, in this case to <strong>get only those posts that their primary tag is the same as the current post</strong> (there&apos;s a slightly difference).</p><p>Optionally, you can use the <code>featured:true</code> filter option to <strong>get those posts that are checked as featured</strong> within the Admin.</p><pre><code class="language-mustache">{{#get &quot;posts&quot; filter=&quot;tags:[{{post.tags}}]+featured:true+id:-{{post.id}}&quot; as |related|}}
    ...
{{/get}}</code></pre><p>If you have multiple writers in your blog and you want to <strong>show related posts where the current author also participates</strong> you can use the <code>authors:{{post.primary_author.slug}}</code> option within the filters.</p><pre><code>{{#get &quot;posts&quot; filter=&quot;authors:{{post.primary_author.slug}}+id:-{{post.id}}&quot; as |related|}}
    ...
{{/get}}</code></pre><p>This is different than using <code>primary_author:{{post.primary_author.slug}}</code> where we are <strong>filtering by those posts where the primary author is the same</strong>.</p><p>Refer to the <a href="https://ghost.org/docs/api/v3/handlebars-themes/helpers/get/?ref=naguel.com">get documentation on Ghost</a> for more ideas on how to filter.</p>]]></content:encoded></item><item><title><![CDATA[Screwing up badly at work]]></title><description><![CDATA[I changed a configuration on a client's site that triggered thousands of emails to different customers. Shit happens, and people make mistakes. I did on that occasion, and I will again in the future, but at least I'll be happy if we, as a team, don't make the exact same mess I did again.]]></description><link>https://naguel.com/screwing-up-badly-at-work/</link><guid isPermaLink="false">5fcbf865e872a900394e67a6</guid><category><![CDATA[Work experiences]]></category><dc:creator><![CDATA[Nahuel Sanchez]]></dc:creator><pubDate>Mon, 30 Nov 2020 13:10:00 GMT</pubDate><media:content url="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/2025/11/Screwing-up-badly-at-work.png" medium="image"/><content:encoded><![CDATA[<img src="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/2025/11/Screwing-up-badly-at-work.png" alt="Screwing up badly at work"><p>I changed a configuration on a client&apos;s site that triggered thousands of emails to different customers, which forced our client&apos;s Customer Service team to handle the same number of customer calls in a single day that they would usually receive over a normal week. They even had to write an apology email for all affected users, assuring them there was no data breach on the site.</p><p>It was a long day.</p><h2 id="admit-it">Admit it</h2><p>Shit happens, and people make mistakes. I did on that occasion, and I will again in the future, or somebody else will, but at least I&apos;ll be happy if we, as a team, don&apos;t make the exact same mess I did again.</p><p>The first thing to do when you screw up is to admit it: tell somebody that you screwed up and explain exactly how.</p><p>If there&apos;s a big problem, and you alone caused it, chances are people will be chasing ghosts to fix something they won&apos;t fully understand if you don&apos;t come forward and tell them exactly what happened.</p><p>You are the only one that knows, basically (until everybody finds out).</p><p>The goal is to shift everybody&apos;s mindset from panicking about a mystery error to focusing on putting out the fire and doing some damage control. Back to my example: everybody was wondering how the emails went out, but when I told them it was me who had changed a setting, everybody moved towards finding a solution (emails were still going out at that point).</p><p>Trying to cover up something is really a stupid idea because, again, shit happens and it shouldn&apos;t be the end of the world. In any case, people will find out rather sooner than later.</p><h2 id="say-sorry-as-you-should-be">Say sorry as you should be</h2><p>Being on the defense on this type of situations is pretty common, but you shouldn&apos;t be. You made a mistake, you admitted it, now apologise without making excuses or blaming something (or somebody) else.</p><p>As individuals and as a team we should learn some stuff starting with the fact that human error is an actual thing. Saying sorry is as important as learning to accept someone&apos;s apology.</p><p>Keep in mind that if you didn&apos;t screw up this time, you could be the one causing the mess next time, so don&apos;t believe you&apos;re so perfect. At the same time, if you were the cause of all the problems today, take a breath, somebody else will take that leading role next time.</p><h2 id="not-the-same-mistake-twice">Not the same mistake twice</h2><p>When the adrenaline is over and the problem is solved do everything within your reach to avoid the same mess to repeat itself.</p><p>Let&apos;s try to have new problems, not always the same ones (it&apos;s boring otherwise).</p><p>While all human errors can&apos;t be eliminated (unless there&apos;s no human in the equation) we can always reduce the chances for them to happen by identifying what mechanism we (the team) can put in place to prevent them.</p><p>Back to my emails: the setting I changed wasn&apos;t on the Live site but on a testing environment that happened to contain real customer data. In this case, the problem was in how we create those testing environments (a fault in the process we have in place).</p><p>The problems could be prevented by improving the processes, adding any necessary documentation, and most important by spreading the information across the team.</p><p>Learning from a mistake isn&apos;t a clich&#xE9;; it&apos;s something tangible.</p><p>If you really learned from a mistake, you will end up with more documentation available to the team, a better process in place, and everybody informed about what happened and what can be done to avoid it happening again.</p><hr><p>Always keep in mind that, in 2017, La La Land was announced as the winner of the Best Picture category at the Oscars because somebody handed the wrong envelope. And they improved the process afterwards.</p>]]></content:encoded></item><item><title><![CDATA[Configure the Terminal to use MAMP's PHP]]></title><description><![CDATA[The idea of changing the Command-line to start using the PHP coming with MAMP is to be able to switch rapidly between PHP versions and to have the configuration for PHP in only one place.

This is easy to implement and it covers how to configure the Terminal to use the same php.ini MAMP uses.]]></description><link>https://naguel.com/configure-the-terminal-to-use-mamp-php/</link><guid isPermaLink="false">5fcbe2f1e872a900394e6686</guid><category><![CDATA[Command-line]]></category><category><![CDATA[MAMP]]></category><category><![CDATA[PHP]]></category><category><![CDATA[Web development]]></category><dc:creator><![CDATA[Nahuel Sanchez]]></dc:creator><pubDate>Mon, 05 Oct 2020 22:37:00 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1590870102494-ab6ed490f869?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MXwxMTc3M3wwfDF8c2VhcmNofDIyfHx8ZW58MHx8fA&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1590870102494-ab6ed490f869?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MXwxMTc3M3wwfDF8c2VhcmNofDIyfHx8ZW58MHx8fA&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" alt="Configure the Terminal to use MAMP&apos;s PHP"><p>By default, after installation, MAMP will make its PHP binaries &quot;available on the browser&quot; while the Terminal will keep on using the system&apos;s PHP with its own configuration.</p><p>The idea behind changing the Command-line to start using the PHP coming with MAMP and its configuration is to be able to switch rapidly between PHP versions and to have the configuration for PHP in only one place.</p><p>Out there you can find enough guides that helps you archive this because, frankly, there are plenty of methods to get this done. This next one is how I personally do it because it&apos;s easy to implement and it also covers something most of other guides won&apos;t which is configure the Terminal to also use the same <code>php.ini</code> MAMP uses.</p><h2 id="configuring-the-command-line-to-use-mamp-s-php">Configuring the Command-line to use MAMP&apos;s PHP</h2><p>You need to edit your Terminal&apos;s Profile in order to add the following to the end:</p><pre><code class="language-Shell">#export PATH=/Applications/MAMP/bin/php/php7.1.33/bin:$PATH
#export PATH=/Applications/MAMP/bin/php/php7.2.33/bin:$PATH
export PATH=/Applications/MAMP/bin/php/php7.3.21/bin:$PATH
#export PATH=/Applications/MAMP/bin/php/php7.4.9/bin:$PATH</code></pre><p>As you can see I&apos;m adding a different line per PHP version I want to potentially have available on the Command-line (PHP 7.1.33, PHP 7.2.33, etcetera) but having them all but one (PHP 7.3.21) commented with the <code>#</code> at the beginning.</p><p>Every time you switch the PHP version in MAMP you should come back to the Profile and leave uncomment the same version so the Terminal and MAMP match.</p><p>Your Command-line&apos;s Profile file depends on your shell. If you are using the default Terminal coming with macOS chances are the Profile will either be <code>~/.bash_profile</code> or <code>~/.bashrc</code>. Mines it&apos;s <code>~/.zshrc</code> because I use <a href="https://ohmyz.sh/?ref=naguel.com">Oh My Zsh</a>.</p><p>Remember that everytime you change your Profile you need to &quot;reload&quot; it by doing <code>source ~/.bash_profile</code> (or whatever file you are using).</p><p>You can check if everything was applied as expected by executing <code>php --ini</code> and seeing the paths are pointing to MAMP.</p><figure class="kg-card kg-image-card"><img src="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/2020/12/configure-terminal-to-use-mamp-php-01-1.png" class="kg-image" alt="Configure the Terminal to use MAMP&apos;s PHP" loading="lazy" width="1420" height="1146" srcset="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w600/2020/12/configure-terminal-to-use-mamp-php-01-1.png 600w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w1000/2020/12/configure-terminal-to-use-mamp-php-01-1.png 1000w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/2020/12/configure-terminal-to-use-mamp-php-01-1.png 1420w" sizes="(min-width: 720px) 720px"></figure><h2 id="configuring-the-command-line-to-use-mamp-s-php-ini">Configuring the Command-line to use MAMP&apos;s php.ini</h2><p>Here&apos;s something interesting about MAMP Pro: it generates, each time it starts, the final <code>php.ini</code> file it will be using during the execution as its content depends on the settings configured on the software&#x2019;s UI.</p><p>For example, if you enable/disable Xdebug on MAMP by ticking/unticking the checkbox on the app, MAMP will regenerate the <code>php.ini</code> file with your configuration (this is basically how MAMP applies any setting change that you perform from the UI).</p><p>The final generated <code>php.ini</code> file is located at <code>/Library/Application Support/appsolute/MAMP PRO/conf/php.ini</code>.</p><p>We already configured the Terminal to use MAMP&apos;s PHP binaries but we also need to configure it to use the generated <code>php.ini</code> by going to <code>/Applications/MAMP/bin/php/php7.3.21/conf</code> (where the not auto generate <code>php.ini</code> file is located) and delete it (after a back up).</p><p>Then we need to create a symlink called <code>php.ini</code> for <code>/Library/Application Support/appsolute/MAMP PRO/conf/php.ini</code> (which is the auto generated one by MAMP) by doing:</p><pre><code class="language-Shell">ln -sf /Library/Application\ Support/appsolute/MAMP\ PRO/conf/php.ini php.ini</code></pre><p>The <code>conf</code> folder should ended up looking like this:</p><figure class="kg-card kg-image-card"><img src="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/2020/12/configure-terminal-to-use-mamp-php-02.png" class="kg-image" alt="Configure the Terminal to use MAMP&apos;s PHP" loading="lazy" width="1420" height="1146" srcset="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w600/2020/12/configure-terminal-to-use-mamp-php-02.png 600w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w1000/2020/12/configure-terminal-to-use-mamp-php-02.png 1000w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/2020/12/configure-terminal-to-use-mamp-php-02.png 1420w" sizes="(min-width: 720px) 720px"></figure><p>Of course the example is for PHP 7.3.21 but you will need to repeat this for the folder of each PHP version you will be using on the Command-line.</p><p>This only applies to MAMP Pro as the non-Pro version doesn&apos;t generates any <code>php.ini</code> and if you want to change something you need to edit the original file yourself.</p>]]></content:encoded></item><item><title><![CDATA[Create and apply a patch in Magento]]></title><description><![CDATA[Magento usually has bugs after the release of a version, that are later corrected on subsequent releases.

Using patches to change core files is not a bad practice when the goal behind it is to bring core fixes existing on newer versions to the one we have running, avoiding so a full upgrade.]]></description><link>https://naguel.com/create-and-apply-a-patch-in-magento/</link><guid isPermaLink="false">60a6dbaa3edfb6003b686bad</guid><category><![CDATA[Magento]]></category><category><![CDATA[Magento 2]]></category><category><![CDATA[Composer]]></category><dc:creator><![CDATA[Nahuel Sanchez]]></dc:creator><pubDate>Wed, 23 Sep 2020 21:05:00 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1526040652367-ac003a0475fe?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDUxfHxjb2ZmZWUlMjBjb2RlfGVufDB8fHx8MTYyMjkyNjkyMA&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1526040652367-ac003a0475fe?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDUxfHxjb2ZmZWUlMjBjb2RlfGVufDB8fHx8MTYyMjkyNjkyMA&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" alt="Create and apply a patch in Magento"><p>Magento usually has bugs (thank you, Captain Obvious) after the release of a version, that are later corrected on subsequent releases (known issues).</p><p>Using patches to change core files in Magento is not a bad practice when the goal behind it is to bring core fixes existing on newer versions to the one we have running, avoiding so a full upgrade.</p><h2 id="how-to-apply-a-patch">How to apply a patch</h2><p>I&apos;m starting the other way around as applying a patch might be more common than actually creating one, specially because Magento itself releases patches for its own platform, third-party vendors release patches for their extensions, and the community also makes patches for others to use.</p><p>There&apos;s a well known Composer package named <a href="https://github.com/cweagans/composer-patches?ref=naguel.com">cweagans/composer-patches</a> that handles the patches and applies them to the original Magento modules every time you run <code>composer install</code> and/or <code>composer update</code>.</p><p>Technically speaking, this tool installs all Composer packages required, then removes the Magento modules affected by the patches we are including, and re-install those modules with the code changes applied.</p><pre><code class="language-bash">&#x279C;  ~ composer install
Gathering patches from patch file.
Removing package magento/module-customer so that it can be re-installed and re-patched.
  - Removing magento/module-customer (102.0.5)
Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Package operations: 1 install, 0 updates, 0 removals
Gathering patches from patch file.
Gathering patches for dependencies. This might take a minute.
  - Installing magento/module-customer (102.0.5): Loading from cache
  - Applying patches for magento/module-customer
    patches/composer/magento/module-customer/22952.patch (#22952 - Delegated account creation fails with custom attributes present in customer address)</code></pre><p>For making this happen, first you need to add your <code>.patch</code> file in the <code>patches/composer/magento/[module-name]/</code> folder (relative to the Magento root, at the same level your <code>composer.json</code> file lives).</p><p>The name of the <code>.patch</code> file doesn&apos;t really matter, but I personally like to use the number of the GitHub issue where the known issue was discussed, if that even exists. Otherwise, any descriptive name would do.</p><p>For the <code>[module-name]</code> folder name use the Composer package name containing the files you are patching.</p><p>As an example, the Composer package name for the <code>Magento_Customer</code> module is <code>module-customer</code>. This information is on the <code>composer.json</code> file of each package, inside the <code>vendor</code> folder.</p><p>Finally, on the root <code>composer.json</code> file, inside the <code>extra</code> node create the <code>patches</code> node and define the patch to apply as the following example.</p><pre><code class="language-json">&quot;extra&quot;: {
    &quot;composer-exit-on-patch-failure&quot;: true,
    &quot;patches&quot;: {
        &quot;magento/module-customer&quot;: {
            &quot;#22952 - Delegated account creation fails with custom attributes present in customer address&quot;: &quot;patches/composer/magento/module-customer/22952.patch&quot;
        }
    }
}</code></pre><p>See that I&apos;m adding a description to what the patch does, and the GitHub issue number, followed by the relative path to the <code>.patch</code> file itself.</p><h2 id="how-to-create-a-patch">How to create a patch</h2><p>Identify the core file you would like to change using a patch.</p><p>For the sake of an example, I&apos;m going to patch the <code>vendor/magento/module-customer/Model/Address.php</code> file to apply a fix for the &quot;<a href="https://github.com/magento/magento2/issues/22952?ref=naguel.com">Delegated account creation fails with custom attributes present in customer address</a>&quot; issue reported in the <a href="https://github.com/magento/magento2?ref=naguel.com">magento/magento2</a> repo itself.</p><p>Create an exact copy of the file, and make all the necessary changes.</p><p>If you are using PhpStorm, you can create a &quot;scratch file&quot; to hold any code temporary, like a draft, by pressing <code>CMD + Shift + N</code>.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/2021/06/create-and-apply-a-patch-in-magento-01.png" class="kg-image" alt="Create and apply a patch in Magento" loading="lazy" width="2000" height="1211" srcset="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w600/2021/06/create-and-apply-a-patch-in-magento-01.png 600w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w1000/2021/06/create-and-apply-a-patch-in-magento-01.png 1000w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w1600/2021/06/create-and-apply-a-patch-in-magento-01.png 1600w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w2400/2021/06/create-and-apply-a-patch-in-magento-01.png 2400w" sizes="(min-width: 1200px) 1200px"><figcaption>Comparison between the original file and the one with the changes</figcaption></figure><p>Output the changes into a <code>.patch</code> file using the <code>diff</code> command on the Terminal while standing in the root of your Magento.</p><pre><code class="language-bash">&#x279C;  ~ diff -Naur path/to/old/file.php path/to/new/file.php &gt; example.patch</code></pre><p>Following my example, I need to execute the following...</p><pre><code class="language-bash">~ diff -Naur vendor/magento/module-customer/Model/Address.php /Users/nahuelsanchez/Library/Application\ Support/JetBrains/PhpStorm2021.1/scratches/scratch_113.php &gt; example.patch</code></pre><p>...in order to get my <code>example.patch</code> file.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/2021/06/create-and-apply-a-patch-in-magento-02.png" class="kg-image" alt="Create and apply a patch in Magento" loading="lazy" width="2000" height="1211" srcset="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w600/2021/06/create-and-apply-a-patch-in-magento-02.png 600w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w1000/2021/06/create-and-apply-a-patch-in-magento-02.png 1000w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w1600/2021/06/create-and-apply-a-patch-in-magento-02.png 1600w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w2400/2021/06/create-and-apply-a-patch-in-magento-02.png 2400w" sizes="(min-width: 1200px) 1200px"><figcaption>My example.patch file generated before any manual intervention</figcaption></figure><p>Unfortunately, here&apos;s when we need to perform some manual intervention on the generated <code>example.patch</code> file.</p><p>First, remove the date and time appearing the end of the first two lines.</p><p>Second, you can see that the first path is the real path to the original file living in the <code>vendor</code> folder. Add a <code>a/</code> prefix to it.</p><p>Third, replace the second path with the first path, but using the <code>b/</code> prefix instead.</p><p>Fourth, and finally, add a new line on top of everything with <code>diff --git a/vendor/core/file.php b/vendor/core/file.php</code>.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/2021/06/create-and-apply-a-patch-in-magento-03.png" class="kg-image" alt="Create and apply a patch in Magento" loading="lazy" width="2000" height="1211" srcset="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w600/2021/06/create-and-apply-a-patch-in-magento-03.png 600w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w1000/2021/06/create-and-apply-a-patch-in-magento-03.png 1000w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w1600/2021/06/create-and-apply-a-patch-in-magento-03.png 1600w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w2400/2021/06/create-and-apply-a-patch-in-magento-03.png 2400w" sizes="(min-width: 1200px) 1200px"><figcaption>Before and after the manual intervention on my example.patch file</figcaption></figure><p>Do not touch anything else there, not even the empty lines at the end (if any).</p><p>The resulting file ready to be used as a patch should look as the following example:</p><pre><code>diff --git a/vendor/magento/module-customer/Model/Address.php b/vendor/magento/module-customer/Model/Address.php
--- a/vendor/magento/module-customer/Model/Address.php
+++ b/vendor/magento/module-customer/Model/Address.php
@@ -159,7 +159,9 @@
         $customAttributes = $address-&gt;getCustomAttributes();
         if ($customAttributes !== null) {
             foreach ($customAttributes as $attribute) {
-                $this-&gt;setData($attribute-&gt;getAttributeCode(), $attribute-&gt;getValue());
+                if (isset($attribute)) {
+                    $this-&gt;setData($attribute-&gt;getAttributeCode(), $attribute-&gt;getValue());
+                }
             }
         }</code></pre>]]></content:encoded></item><item><title><![CDATA[Lazyload post Feature Image from Unsplash in Ghost]]></title><description><![CDATA[The image from Unsplash is big and impacts on the page speed of the site since the browser will download the image first then continue with the rest of the page.

There's no much we can do about the image size but with a little bit of HTML and JS we can lazy load them to prioritize the content.]]></description><link>https://naguel.com/lazyload-post-feature-image-from-unsplash-in-ghost/</link><guid isPermaLink="false">5ffb39ab2473770039698186</guid><category><![CDATA[Ghost]]></category><category><![CDATA[Page Speed]]></category><category><![CDATA[Performance]]></category><category><![CDATA[Web development]]></category><dc:creator><![CDATA[Nahuel Sanchez]]></dc:creator><pubDate>Thu, 20 Aug 2020 18:48:00 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1595001919591-9cbba22bb05b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MXwxMTc3M3wwfDF8c2VhcmNofDEzfHxjb2ZmZWUlMjBjbG9ja3xlbnwwfHx8&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1595001919591-9cbba22bb05b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MXwxMTc3M3wwfDF8c2VhcmNofDEzfHxjb2ZmZWUlMjBjbG9ja3xlbnwwfHx8&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" alt="Lazyload post Feature Image from Unsplash in Ghost"><p>Unsplash is a great Ghost built-in integration that allows you to quickly add an image to your posts, and I personally use it every time to add the Feature Image to all my articles (the big one below the title, before the content).</p><p>Unfortunately, out of the box the image from Unsplash is really big (2000px wide) and impacts on the page speed of the site since the browser will download the image first then continue with the rest of the page.</p><p>There&apos;s no much we can do about the image size as we can&apos;t follow the &quot;<a href="https://ghost.org/docs/themes/assets/?ref=naguel.com#responsive-images-configuration">How to use responsive images in Ghost themes</a>&quot; official guide because that only applies to images you manually upload and not those coming from third-parties...</p><blockquote>Dynamic image sizes are <em>not</em> compatible with externally hosted images. If you insert images from Unsplash or you store your image files on a third party storage adapter then the image url returned will be determined by the external source.</blockquote><p>...but with a little bit of HTML and JavaScript we can lazy load them to prioritize the content over the image download.</p><p>Usually, the Feature Image in the Ghost theme will look something like:</p><pre><code class="language-HTML">&lt;img src=&quot;{{feature_image}}&quot; /&gt;</code></pre><p>This is a classic <code>img</code> tag with the <code>src</code> containing the URL of the image. But we need to do some changes here first before moving to the JS side of this technique.</p><p>In the <code>src</code> we are going to put a placeholder image to avoid having a broken image while the rest of the page loads, we are going to move the actual image to the <code>data-src</code> attribute, and finally we&apos;ll add a new class to the element.</p><pre><code class="language-HTML">&lt;img src=&quot;{{asset &quot;images/placeholder.png&quot;}}&quot; data-src=&quot;{{feature_image}}&quot; class=&quot;lazyload&quot; /&gt;
</code></pre><p>The placeholder image should be a small image in terms of weight. I&apos;m using an image with a solid colour of 183 bytes so I can &quot;reserve&quot; the space of the final Feature Image to avoid &quot;jumps&quot; in the browser while everything loads.</p><p>Finally, the JS is quite simple. We need to wait for the <code>window</code> to be loaded, get all the <code>img</code> elements with the <code>lazyload</code> class, and replace the <code>src</code> with what&apos;s on the <code>data-src</code> so we trigger the actual image download.</p><pre><code class="language-JavaScript">window.addEventListener(&apos;load&apos;, (event) =&gt; {
    let images = document.getElementsByClassName(&apos;lazyload&apos;);

    for (let i = 0; i &lt; images.length; i++) {
        images[i].src = images[i].dataset.src;
    }
});</code></pre><p>With this in place we should see that the content is prioritized over the Unsplash image, and if we are using a placeholder we should see that first in the &quot;<em>Network</em>&quot; tab of our browser&apos;s DevTools, with the actual image loading later.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/2021/01/lazyload-post-feature-image-from-unsplash-in-ghost-01.png" class="kg-image" alt="Lazyload post Feature Image from Unsplash in Ghost" loading="lazy" width="2000" height="1146" srcset="https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w600/2021/01/lazyload-post-feature-image-from-unsplash-in-ghost-01.png 600w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w1000/2021/01/lazyload-post-feature-image-from-unsplash-in-ghost-01.png 1000w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/size/w1600/2021/01/lazyload-post-feature-image-from-unsplash-in-ghost-01.png 1600w, https://storage.ghost.io/c/d7/8d/d78d3a2b-52dd-4fe9-9364-cf289fba7ead/content/images/2021/01/lazyload-post-feature-image-from-unsplash-in-ghost-01.png 2304w" sizes="(min-width: 1200px) 1200px"></figure>]]></content:encoded></item><item><title><![CDATA[Having a successfully work from home lifestyle]]></title><description><![CDATA[Working from home is the new normal, get used to it and get ready, because what's now a benefit will be a requirement in the not too distant future.]]></description><link>https://naguel.com/having-a-successfully-work-from-home-lifestyle/</link><guid isPermaLink="false">5b4c91f71b711f00bf9c306a</guid><category><![CDATA[Work from home]]></category><category><![CDATA[Remote working]]></category><dc:creator><![CDATA[Nahuel Sanchez]]></dc:creator><pubDate>Sun, 12 Jul 2020 04:14:33 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1497048679117-1a29644559e3?ixlib=rb-1.2.1&amp;q=80&amp;fm=jpg&amp;crop=entropy&amp;cs=tinysrgb&amp;w=2000&amp;fit=max&amp;ixid=eyJhcHBfaWQiOjExNzczfQ" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1497048679117-1a29644559e3?ixlib=rb-1.2.1&amp;q=80&amp;fm=jpg&amp;crop=entropy&amp;cs=tinysrgb&amp;w=2000&amp;fit=max&amp;ixid=eyJhcHBfaWQiOjExNzczfQ" alt="Having a successfully work from home lifestyle"><p>This is the new normal, get used to it and get ready, because what&apos;s now (somehow still) a benefit from a company will be a requirement in the not too distant future. I wouldn&apos;t be surprised if working from home becomes a skill on a job offer rather than a perk.</p><p>Imagine listing on your resume not only your English level but also your work from home seniority.</p><p>All the lockdowns imposed around the globe due to the Covid-19 situation forced companies into a WFH scheme where everybody went remote from day to night.</p><p>I think this is here to stay in a combination of remote working and office space, resulting on a true flexible work from home scheme, because this is not only better for the employee but also cheaper for a company (no more rent?).</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://naguel.com/no-more-bs-against-working-from-home-thanks-to-a-pandemic/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">No more bs against working from home thanks to a pandemic</div><div class="kg-bookmark-description">Companies were forced to reorganize quickly to continue working with their employees from home: the bs around this was cut immediately, the scepticism towards having people working from their homes disappeared. It had too, there was no other option.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://naguel.com/favicon.png" alt="Having a successfully work from home lifestyle"><span class="kg-bookmark-author">Naguel</span><span class="kg-bookmark-publisher">Nahuel Sanchez</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://images.unsplash.com/photo-1545239351-ef35f43d514b?ixlib=rb-1.2.1&amp;q=80&amp;fm=jpg&amp;crop=entropy&amp;cs=tinysrgb&amp;w=2000&amp;fit=max&amp;ixid=eyJhcHBfaWQiOjExNzczfQ" alt="Having a successfully work from home lifestyle"></div></a></figure><p>I had the luxury of a WFH benefit on my last job and now, for the past two years, I became a full time remote employee to a London-based eCommerce agency so I sort of know how to work from home, and I don&apos;t see myself ever again going to an office Monday to Friday, so here&apos;s my take with three aspects on how to nail working from home.</p><h2 id="your-space-in-the-house">Your space in the house</h2><p>My first ever mistake (and probably everybody&apos;s first ever mistake) when I started to work from home everyday was to use the same table where I ate as my desk too.</p><p>The problem is not the table itself and the fact that the Mac shares it with a slice of pizza, but the inner feeling of being always on the same place, always, all the time, when working and when not doing it.</p><p>So even if you disconnect from Slack or close the lid, you are always at your working station, which is not good (mentally speaking).</p><p>Having a room in your house as the office is the main recommendation somebody could give you when diving into the work from home culture because it will easily allow you to &quot;call it a day&quot; when you have to, the same way you picked up your things from your desk at the company building and returned home.</p><p>Sometimes you&apos;ll need to isolate from the rest of the house when living with somebody else, on situations like having to concentrate on a task or having a Zoom meeting so here&apos;s where a door will come at handy, or some noise-cancelling headphones.</p><p>This leads us to having a set of house rules for all the house members for when work is happening, because not everybody is used to this work from home scheme and there was no reason at all until now to be aware of this new normal and having somebody in the house that now works from it.</p><p>For example, I tend to announce that I&apos;m going to start a meeting, and that&apos;s enough for me. But you can set other rules too, like &quot;Headphones means no interruptions&quot;, or guidelines for when the office door is closed.</p><p>Surely, I understand that having a spare room to be used as an office is usually a luxury, I&apos;m no idiot.</p><p>For example, I rented my current place with this objective in mind, and I&apos;m sure this will be something that&apos;s going to be considered, in the future, for when renting and/or moving.</p><p>But, still, there&apos;s always something you can do to mentally disconnect from work when you are done with it.</p><p>If you can&apos;t have a separate room, you maybe can have a specific place in the house to work, which is not the table where you eat. Like a small desk on the dinner or living room, that you know you use only for working.</p><p>Even if there&apos;s no physical space to do so, and you are forced no matter what to use the dinner table for working, then you can rely on environment settings to differentiate working hours from free time (like lighting).</p><p>Finally, something that works when there&apos;s no office room in the house is to close the computer and save it on a drawer, as a big gesture to call it a day.</p><h2 id="a-routine-to-avoid-burnouts">A routine to avoid burnouts</h2><p>One of the main problems of working from one, that we already mentioned as partially solvable by having a dedicated physical space to work, is the feeling of being on a constant work mode, on a state where work and life get mixed together and there&apos;s no clear differentiation between one and the other.</p><p>Having to go to an office imposed, at some capacity, a routine that you had to follow like waking up at a specific hour, having to take a shower for the sake of respecting your coworkers, having breakfast, etcetera.</p><p>Now you have to set your own routine, which is easy, and follow it, which is not.</p><p>This starts with having to follow regular hours every day, a routine. For example, I have set on my smartwatch reminders to have breakfast and lunch, which is a way to avoid losing track of time when I&apos;m working.</p><p>Even if I do not actually follow them on a day because &quot;<em>I&apos;m too busy</em>&quot; or because &quot;<em>I need to finish this first</em>&quot;, it&apos;s a way to take awareness of &quot;when are we&quot;.</p><p>You don&apos;t need to actually get up hours before work to take a shower, that clearly can be done later, but you shouldn&apos;t get up a minute before checking in at work. Allow you at least 15 minutes of being up and running before sitting on your desk.</p><p>I know that stay in bed for as much as we can is temping, and it&apos;s a clear benefit of working from home. But that&apos;s the benefit of not commuting, that&apos;s from where we gain sleeping hours.</p><p>So, 15 minutes of sleep won&apos;t make you any difference, but having 15 minutes for you before starting to work results on being more awake, therefore rested, through the entire day.</p><p>For a better working day, work on having a better wake up routine.</p><p>You don&apos;t have to have breakfast before work, that doesn&apos;t have to necessarily be part of your wake up routine, but instead you can have it later, during work, as a break.</p><p>Pause work during working hours to have breakfast? Isn&apos;t that against the rules? Please! When you were at the office you had some water cooler moments, or stop by the desk of a coworker to have some chat about whatever, or you made yourself five cups of coffee.</p><p>You had your breaks at the office and it&apos;s fine to have them now at home.</p><h2 id="call-it-a-day">Call it a day</h2><p>Avoid falling into an eternal working state of mind, or workaholism, is what you will be constantly fighting while working for home if you don&apos;t train yourself to be better at remote working.</p><p>Stop working is part of being good at it.</p><p>If the company you work for doesn&apos;t care for time tracking, you should track your time anyway, for yourself, to be aware of how much are you spending at work. And, as if you were going to an office, you should call it a day at some point, and don&apos;t work until the next day.</p><p>At the company I work for we have a Slack reminder with some stuff before we go, which also works as a reminder of what time is it (the same as the use of an alarm or the reminders I already mentioned I have on my smartwatch).</p><p>And when it&apos;s time to go. Go. No, really, go. Whatever it is, with the exception of an emergency, can be continued tomorrow... or next week.</p><p>If you can go out after calling it a day, even better. Leaving home is very good to clear your mind, even if it&apos;s for a short walk or for having a moment at a coffee store (which is my thing).</p><hr><p>Working from home was always a luxury I can see becoming the new normal after this big social experiment we all suffered due to the pandemic.</p><p>Internet is full of tips and tricks on how to succeed at working from home. You just need to find those that suit you and get on with it.</p>]]></content:encoded></item></channel></rss>