<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Duncan McDougall | Web Developer</title>
    <subtitle></subtitle>
    <link href="https://www.belter.io/feed.xml" rel="self"/>
    <link href="https://www.belter.io/"/>
    <updated>2025-11-23T17:16:48Z</updated>
    <id>https://www.belter.io</id>
    <author>
        <name>Duncan McDougall</name>
        <email>duncanmcdougall@belter.io</email>
    </author>
    
        
        <entry>
            <title>Delay Loading The Print Stylesheet</title>
            <link href="https://www.belter.io/delay-loading-print-stylesheet/"/>
            <updated>2010-07-20T00:00:00Z</updated>
            <id>https://www.belter.io/delay-loading-print-stylesheet/</id>
            <content type="html">
                <![CDATA[
      <p>Update: Deferred downloading of print stylesheets is coming to a <a href="http://trac.webkit.org/changeset/73938">future release of WebKit</a>.</p>
<p>Browsers can only download a limited number of files at a time from the same host when loading a web page. This is as low as 2 files on IE 6 &amp; 7.</p>
<p>To allow the page to appear faster a best practise is to prioritise important files like the main CSS, template images and the main content. Since the print stylesheet is rarely used, especially not within the first few seconds of page load I recommend loading this file last.</p>
<p>This isn’t as simple as referencing the file at the end of your HTML since in some browsers the page is not rendered until all CSS is loaded. A JavaScript solution is required. Add the following JS to load on document load.</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">function</span> <span class="token function">LoadPrint</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br>  <span class="token keyword">var</span> headTag <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementsByTagName</span><span class="token punctuation">(</span><span class="token string">"head"</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br>  <span class="token keyword">var</span> printCss <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">"link"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>  printCss<span class="token punctuation">.</span>type <span class="token operator">=</span> <span class="token string">"text/css"</span><span class="token punctuation">;</span><br>  printCss<span class="token punctuation">.</span>rel <span class="token operator">=</span> <span class="token string">"stylesheet"</span><span class="token punctuation">;</span><br>  printCss<span class="token punctuation">.</span>href <span class="token operator">=</span> <span class="token string">"/css/print.css"</span><span class="token punctuation">;</span><br>  printCss<span class="token punctuation">.</span>media <span class="token operator">=</span> <span class="token string">"print"</span><span class="token punctuation">;</span><br>  headTag<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>printCss<span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>noscript</span><span class="token punctuation">></span></span><br>  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>link</span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>stylesheet<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text/css<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/css/print.css<span class="token punctuation">"</span></span> <span class="token attr-name">media</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>print<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>noscript</span><span class="token punctuation">></span></span></code></pre>
<p>I’ve avoided using jQuery’s appendTo as during my testing IE7 didn’t like it. Barebones JavaScript will do. Now for the no JavaScript use the noscript tag in the head to load the print stylesheet in the normal position.</p>
<p>The savings won’t be huge but every little helps so why not.</p>
<p>See also: <a href="http://www.phpied.com/delay-loading-your-print-css/">Delay loading your print css</a> - Stoyan Stefanov</p>

    ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Slow Site, Frustrated Visitors, Negative Press</title>
            <link href="https://www.belter.io/slow-sites-and-bad-press/"/>
            <updated>2011-01-23T00:00:00Z</updated>
            <id>https://www.belter.io/slow-sites-and-bad-press/</id>
            <content type="html">
                <![CDATA[
      <p>In my last post I referenced <a href="https://www.seanpower.com/">Sean Power's</a> findings that as much as 37-49% of visitors who experience performance issues will either abandon the site or switch to a competitor. As much as 77% will go on to share their experiences with others <a href="http://www.slideshare.net/bitcurrent/metrics-101">(slide 15)</a>.</p>
<p>I wanted to illustrate this point of sharing bad experiences due to slow websites. Have a go at searching Twitter for <a href="https://twitter.com/search?q=slow%20site&amp;src=typed_query">'slow website'</a> and you will be amazed at the number of people who have vented their frustrations within the last few hours.</p>
<p>Here's a few I've seen in recent days.</p>
<blockquote class="twitter-tweet" data-dnt="true" data-theme="dark"><p lang="en" dir="ltr">Trying to book tickets on <a href="https://twitter.com/SJ_AB?ref_src=twsrc%5Etfw">@SJ_AB</a>, but the site is so slow...</p>&mdash; Thomas Dahlberg (@tdhlbrg) <a href="https://twitter.com/tdhlbrg/status/28111477894291458?ref_src=twsrc%5Etfw">January 20, 2011</a></blockquote>
<blockquote class="twitter-tweet" data-dnt="true" data-theme="dark"><p lang="en" dir="ltr">the o2.ie website is so slow and frustrating <a href="https://twitter.com/hashtag/agghhhhh?src=hash&amp;ref_src=twsrc%5Etfw">#agghhhhh</a></p>&mdash; ronan mcloughlin (@jedi_vincent) <a href="https://twitter.com/jedi_vincent/status/28034621883031552?ref_src=twsrc%5Etfw">January 20, 2011</a></blockquote>
<blockquote class="twitter-tweet" data-dnt="true" data-theme="dark"><p lang="en" dir="ltr">Why is Gap&#39;s website slow? Argh.</p>&mdash; Wordy PR Girl (@WordyPRGirl) <a href="https://twitter.com/WordyPRGirl/status/28167073754517504?ref_src=twsrc%5Etfw">January 20, 2011</a></blockquote>
<p>Websites like Twitter and Facebook mean it's so easy these days to have a wee moan about the frustrations caused by an under performing site. We pay good money for a speedy internet connection so when we can't take full advantage of this due to slow websites, the user experience is quickly soured.</p>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

    ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>How to Remove ETags in IIS6</title>
            <link href="https://www.belter.io/remove-etags-iis6/"/>
            <updated>2011-07-10T00:00:00Z</updated>
            <id>https://www.belter.io/remove-etags-iis6/</id>
            <content type="html">
                <![CDATA[
      <p>If you’ve used tools like YSlow or WebPageTest you may have noticed that one of the suggestions is to turn off ETags.
What are they you ask. An ETag, or entity tag, is an ID assigned to a version of a file by the webserver.
This is used to determine whether the version stored in the browser cache is the same as the one on the server.</p>
<p>The Etag is sent with initial download of the file</p>
<p><code>Etag:&quot;0221921cfdfca1:5b19&quot;</code></p>
<p>When checking for modification the etag is sent in the If-None-Match header</p>
<p><code>If-None-Match:&quot;0221921cfdfca1:5b19&quot;</code></p>
<p>So what’s the problem then. The issue lies when hosting a component on multiple servers. When validating the tag
on a server different from the one it was downloaded from, the file’s tag can be different as they are generated
using server attributes. In IIS 6 the tag is appended with a modification counter, which again is likely to be
different from server to server.</p>
<p>So in essence rather than just telling the browser to pull the file from the cache, it will be re-downloaded.</p>
<p>Since last modification is already in place, lets just stick with that. If your not splitting your site across
multiple servers you can at least benefit from the reduced header size.</p>
<p>Let’s get to switching the bugger off in IIS 6. Luckily, just as in Apache, it’s really easy.</p>
<ol>
    <li>On the website’s entry right click-&gt;properties.</li>
    <li>Select the HTTP Headers tab.</li>
    <li>Add a new entry with Etag as the name, leaving the value blank.</li>
</ol>

    ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Many To Many Mapping in Fluent NHibernate</title>
            <link href="https://www.belter.io/manytomany-fluentnhibernate/"/>
            <updated>2011-10-11T00:00:00Z</updated>
            <id>https://www.belter.io/manytomany-fluentnhibernate/</id>
            <content type="html">
                <![CDATA[
      <p>Here’s a spot of code for mapping two classes in Fluent NHibernate with a many-to-many relation. Say you have Employee and Department classes like so.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Actor</span><br><span class="token punctuation">{</span><br>    <span class="token keyword">public</span> <span class="token keyword">virtual</span> <span class="token return-type class-name"><span class="token keyword">int</span></span> Id <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><br>    <span class="token keyword">public</span> <span class="token keyword">virtual</span> <span class="token return-type class-name"><span class="token keyword">string</span></span> Name <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><br>    <span class="token keyword">public</span> <span class="token keyword">virtual</span> <span class="token return-type class-name">IList</span> Movies <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><br><span class="token punctuation">}</span><br><br><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Movie</span><br><span class="token punctuation">{</span><br>    <span class="token keyword">public</span> <span class="token keyword">virtual</span> <span class="token return-type class-name"><span class="token keyword">int</span></span> Id <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><br>    <span class="token keyword">public</span> <span class="token keyword">virtual</span> <span class="token return-type class-name"><span class="token keyword">string</span></span> Name <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><br>    <span class="token keyword">public</span> <span class="token keyword">virtual</span> <span class="token return-type class-name">IList</span> Actors <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>So obviously a movie can have many actors and an actor could star in multiple movies. Your database will consist of three tables, an actors, a movie and a Cast table. The cast table will pretty much just be our link with ActorId and MovieId foreign keys.</p>
<p>Finally here’s the mapping.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ActorMap</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">ClassMap</span></span><br><span class="token punctuation">{</span><br>    <span class="token keyword">public</span> <span class="token function">ActorMap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br>    <span class="token punctuation">{</span><br>        <span class="token function">Id</span><span class="token punctuation">(</span>x <span class="token operator">=></span> x<span class="token punctuation">.</span>Id<span class="token punctuation">)</span><span class="token punctuation">;</span><br>        <span class="token function">Map</span><span class="token punctuation">(</span>x <span class="token operator">=></span> x<span class="token punctuation">.</span>Name<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>        <span class="token function">HasManyToMany</span><span class="token punctuation">(</span>x <span class="token operator">=></span> x<span class="token punctuation">.</span>Movies<span class="token punctuation">)</span><br>            <span class="token punctuation">.</span><span class="token function">WithTableName</span><span class="token punctuation">(</span><span class="token string">"Cast"</span><span class="token punctuation">)</span><br>            <span class="token punctuation">.</span><span class="token function">WithParentKeyColumn</span><span class="token punctuation">(</span><span class="token string">"ActorId"</span><span class="token punctuation">)</span><br>            <span class="token punctuation">.</span><span class="token function">WithChildKeyColumn</span><span class="token punctuation">(</span><span class="token string">"MovieId"</span><span class="token punctuation">)</span><br>            <span class="token punctuation">.</span><span class="token function">LazyLoad</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br>            <span class="token punctuation">.</span>Cascade<span class="token punctuation">.</span><span class="token function">SaveUpdate</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>    <span class="token punctuation">}</span><br><span class="token punctuation">}</span><br><br><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">MovieMap</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">ClassMap</span></span><br><span class="token punctuation">{</span><br>    <span class="token keyword">public</span> <span class="token function">MovieMap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br>    <span class="token punctuation">{</span><br>        <span class="token function">Id</span><span class="token punctuation">(</span>x <span class="token operator">=></span> x<span class="token punctuation">.</span>Id<span class="token punctuation">)</span><span class="token punctuation">;</span><br>        <span class="token function">Map</span><span class="token punctuation">(</span>x <span class="token operator">=></span> x<span class="token punctuation">.</span>Name<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>        <span class="token function">HasManyToMany</span><span class="token punctuation">(</span>x <span class="token operator">=></span> x<span class="token punctuation">.</span>Actors<span class="token punctuation">)</span><br>            <span class="token punctuation">.</span><span class="token function">WithTableName</span><span class="token punctuation">(</span><span class="token string">"Cast"</span><span class="token punctuation">)</span><br>            <span class="token punctuation">.</span><span class="token function">WithParentKeyColumn</span><span class="token punctuation">(</span><span class="token string">"ActorId"</span><span class="token punctuation">)</span><br>            <span class="token punctuation">.</span><span class="token function">WithChildKeyColumn</span><span class="token punctuation">(</span><span class="token string">"MovieId"</span><span class="token punctuation">)</span><br>            <span class="token punctuation">.</span><span class="token function">Inverse</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>    <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>

    ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Disable Bouncing Scroll Effect in PhoneGap [iOS]</title>
            <link href="https://www.belter.io/disable-bouncing-scroll-phonegap-iphone/"/>
            <updated>2012-08-07T00:00:00Z</updated>
            <id>https://www.belter.io/disable-bouncing-scroll-phonegap-iphone/</id>
            <content type="html">
                <![CDATA[
      <p>When building an iPhone app using PhoneGap by default when you pull down the view on the device or simulator
you can for some reason pull down the entire app before it bounces back into position. In Cordova 1.7 this
is really simple to turn off. I don’t know why it isn’t in the first place, but screw it, on to the instructions.</p>
<p>To turn this effect off open <code>Cordova.plist</code> which can be found in the <strong>Supporting Files</strong>directory.</p>
<p>Look for the <code>UIWebViewBounce</code> entry and change it to <code>NO</code>.</p>
<p>Magic</p>

    ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>iOS Date Parsing Issue</title>
            <link href="https://www.belter.io/ios-date-parsing-issue/"/>
            <updated>2012-08-07T00:00:00Z</updated>
            <id>https://www.belter.io/ios-date-parsing-issue/</id>
            <content type="html">
                <![CDATA[
      <p>The following code works in web browsers but returns <em>&quot;Invalid Date&quot;</em> on iOS 5. I noticed while building a PhoneGap based app.</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token comment">// This returns invalid date in iOS.</span><br><span class="token keyword">var</span> yearMonth <span class="token operator">=</span> <span class="token string">"2012-08"</span><span class="token punctuation">;</span><br><span class="token keyword">var</span> date <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span>yearMonth<span class="token punctuation">)</span><span class="token punctuation">;</span><br>document<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span>date<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h3>Solution</h3>
<p>Split the string into parts and pass in the first two items of the array. Since January is 0 and December is 11,
remember to take 1 from the month value. Should work.</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token comment">// This works in iOS.</span><br><span class="token keyword">var</span> yearMonth <span class="token operator">=</span> <span class="token string">"2012-08"</span><span class="token punctuation">;</span><br><span class="token keyword">var</span> dateParts <span class="token operator">=</span> yearMonth<span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">"-"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token keyword">var</span> date <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span>dateParts<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> dateParts<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>document<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span>date<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>If anyone has a cleaner method to do this, let me know. Much appreciated.</p>

    ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>jQuery Responsive Lightbox plugin</title>
            <link href="https://www.belter.io/responsive-lightbox/"/>
            <updated>2012-11-10T00:00:00Z</updated>
            <id>https://www.belter.io/responsive-lightbox/</id>
            <content type="html">
                <![CDATA[
      <link href="/css/jquery.lightbox.css" rel="stylesheet">
<p>I was recently tasked with finding a lightbox plugin for high traffic e-commerce site I was building from scratch. Given the impact page weight can have on conversion, bounce rates and a bunch of other delicate analytic metrics, it was essential every piece of JavaScript selected for the site was as lightweight as possible, along with being responsive.</p>
<p>Most lightbox plugins that met the responsive requirement came bundled with functionality to display videos, and transitioned from slide to slide in more elaborate ways than the next. I just wanted to popup an image.</p>
<p>I decided to build my own.</p>
<h3>Demo</h3>
<div style="display: flex; justify-content: space-between;">
  <a href="/images/lightbox/sample_a.jpg" data-caption="Gondala ride in Venice" rel="lightbox"><img src="/images/lightbox/sample_a_thumb.jpg" alt="Gondala ride in Venice" /></a>
  <a href="/images/lightbox/sample_b.jpg" data-caption="The Queen's Guard" rel="lightbox"><img src="/images/lightbox/sample_b_thumb.jpg" alt="The Queen's Guard" /></a>
  <a href="/images/lightbox/sample_c.jpg" data-caption="Atomium in Brussels"  rel="lightbox"><img src="/images/lightbox/sample_c_thumb.jpg" alt="Atomium in Brussels" /></a>
  <a href="/images/lightbox/sample_d.jpg" data-caption="London Olympics 2012"  rel="lightbox"><img src="/images/lightbox/sample_d_thumb.jpg" alt="Tower Bridge in London during 2012 Olympics" /></a>
</div>
<p><a href="https://github.com/duncanmcdougall/Responsive-Lightbox">View on GitHub</a></p>
<h3>How to use</h3>
<p>Requires jQuery &gt;= 1.4 and &lt; 3</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>html</span><span class="token punctuation">></span></span><br>  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">></span></span><br>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>link</span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>stylesheet<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>jquery.lightbox.css<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br>  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">></span></span><br>  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">></span></span><br>    <span class="token comment">&lt;!-- Link to the image --></span><br>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>myimage.jpg<span class="token punctuation">"</span></span> <span class="token attr-name">data-caption</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Optional caption attribute<span class="token punctuation">"</span></span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>lightbox<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Click me<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span><br><br>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.js<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">></span></span><br>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>jquery.lightbox.min.js<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">></span></span><br><br>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">></span></span><span class="token script"><span class="token language-javascript"><br>      <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br>        <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">'[rel="lightbox"]'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">lightbox</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>    </span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">></span></span><br>  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">></span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>html</span><span class="token punctuation">></span></span></code></pre>
<p><a href="https://github.com/duncanmcdougall/Responsive-Lightbox">Download files on GitHub</a></p>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.js"></script>
<script src="/js/jquery.lightbox.js"></script>
<script>
  $(function() {
    $('[rel="lightbox"]').lightbox();
  });
</script>

    ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Umbraco Instant Log Out Issue</title>
            <link href="https://www.belter.io/umbraco-instant-logout-issue/"/>
            <updated>2013-09-24T00:00:00Z</updated>
            <id>https://www.belter.io/umbraco-instant-logout-issue/</id>
            <content type="html">
                <![CDATA[
      <p>I recently had an issue with one of my Umbraco sites where I just couldn't log in to the dashboard on my development machine. Firing up Fiddler I found Umbraco was logging me in but instantly logging me back out again by redirecting me to /umbraco/logout.aspx.</p>
<p>The culprit</p>
<pre class="language-xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>httpCookies</span> <span class="token attr-name">requireSSL</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span></code></pre>
<p>A quick web.config transform so this is set to false on localhost saved the day. Huzzah!</p>

    ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Website Speed and Analytic Metrics</title>
            <link href="https://www.belter.io/website-speed-google-analytic-metrics/"/>
            <updated>2013-10-07T22:40:32Z</updated>
            <id>https://www.belter.io/website-speed-google-analytic-metrics/</id>
            <content type="html">
                <![CDATA[
      <p>Opening up Google Analytics you are presented with a bunch of stats about your site’s traffic. What shouldn't be underestimated is the amount of influence website speed has on these values.</p>
<p><img src="/images/analytics.png" alt="Analytics"></p>
<h3>Pages/Visit</h3>
<p>When visiting a snappy site like Amazon, you don't grudge clicking to view a related item. You know you won't be waiting long for content to appear. In a set time period, the less time spent loading, the more ground covered.</p>
<p><img src="/images/amazon-related.png" alt="Related items on Amazon"></p>
<h3>Bounce Rate</h3>
<p>Bounce rate is the percentage of visitors who hit your site but leave, only having viewed one page.</p>
<p><img src="/images/loading-loading-loading.png" alt="Loading Screen"></p>
<p>Google can use your bounce rate in its <a href="http://www.seohermit.com/articles/what-bounce-rate-means-for-your-seo-strategy/">ranking</a>. A site might be completely relevant to what you were looking for but if its sluggishness is forcing visitors to hit the back button, it's understandable when you get knocked down a place.</p>
<h3>Visitors and % New Visitors</h3>
<p>Google looks at your site's speed as quality indicator. You'd prefer the faster of two identical sites, so Google factors this into their ranking algorithm.</p>
<p>If your customers leave satisfied they'll tell a friend, tweet, share on Facebook, blog etc. Lots of links leads to lots of new visitors.</p>
<h3>Returning Visitors</h3>
<p>A frustrating experience is remembered, making me think twice before clicking again next time your site appears on Google. Inversely, I positive experience gets you bookmarked.</p>
<blockquote class="twitter-tweet"><p>Why is <a href="https://twitter.com/search?q=%23onedirection&amp;src=hash">#onedirection</a>&#39;s website so slow, driving me crazy???!!! how to move on if we never break down, <a href="https://twitter.com/search?q=%23iUltimateQuotes&amp;src=hash">#iUltimateQuotes</a></p><cite>&mdash; Donnie Withers (@TpYoshiko) <a href="https://twitter.com/TpYoshiko/statuses/389447489042259968">October 13, 2013</a></cite></blockquote>
<p>One less fan.</p>
<h3>Avg. Visit Duration</h3>
<p>Like me, at some point you'll have visited Amazon to quickly check the price of a new watch of something and before you know it you've burned twenty minutes and your basket is full of stuff from every other department. Nice snappy pages suck you in. Similarly see <a href="http://www.youtube.com/watch?v=hiftQ_YJhps" target="_blank">YouTube</a> and <a href="http://en.wikipedia.org/wiki/Frank_Hayes_%28jockey%29" target="_blank">Wikipedia</a>.</p>
<h3>Conversion</h3>
<p>Your visitors will only dedicate so long to your site. The less time spent loading, the more time left to explore and absorb your content, leading to your finish line regardless of whether that's a checkout or new user signup.</p>
<p>Speed is a indicator of quality and therefore trust. You'll need to have this established this by the time you're asking for card details.</p>

    ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Debugging LESS with dotLESS</title>
            <link href="https://www.belter.io/debugging-less-with-dotless/"/>
            <updated>2015-09-05T00:00:00Z</updated>
            <id>https://www.belter.io/debugging-less-with-dotless/</id>
            <content type="html">
                <![CDATA[
      <p>One feature of <a href="http://www.dotlesscss.org/">dotLESS</a> I find incredibly useful but appears to be a hidden feature is debug=”true”. I say hidden feature because it’s not a default configuration attribute on install or easy to discover in the docs so I’m sure there’s plenty of devs unaware of this handy addition.</p>
<p>If you’re nice and organised you’ll no doubt be splitting your CSS across multiple .less files, compiling to a single .css file with the power of @imports e.g. <code>@import &quot;components\some-component.less&quot;;</code>. It becomes a pain once you get into the browser if you need to trace back a line in the output to where it appears in one of your many .less files.</p>
<p><code>debug=&quot;true&quot;</code> will kindly add a comment above every declaration, pointing you to the file and the line where it originates from.</p>
<p><img src="/images/dotless_hints.png" alt="dotLESS hints"></p>
<p>Edit your web.config to add the new attribute.</p>
<pre class="language-xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dotless</span> <span class="token attr-name">minifyCss</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>false<span class="token punctuation">"</span></span> <span class="token attr-name">cache</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>false<span class="token punctuation">"</span></span> <span class="token attr-name">web</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token attr-name">debug</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span></code></pre>

    ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>My .nvm/default-packages</title>
            <link href="https://www.belter.io/npm-global-packages/"/>
            <updated>2019-04-07T00:00:00Z</updated>
            <id>https://www.belter.io/npm-global-packages/</id>
            <content type="html">
                <![CDATA[
      <p>When it's a package that I'll use infrequently, such as create-react-app, I'll use <code>npx</code>. However, there are some utility packages I use again and again. To install globally either <code>npm i -g &lt;package-name&gt;</code> or even better, add them to <code>~/.nvm/default_packages</code>.</p>
<h3><a href="https://www.npmjs.com/package/rimraf">rimraf</a></h3>
<pre class="language-text"><code class="language-text">npm i -g rimraf<br>rimraf [path]</code></pre>
<p>It's <code>rm -rf</code> but works whereever you have node - macOS, Windows, WSL, node.</p>
<h3><a href="https://www.npmjs.com/package/http-server">http-server</a></h3>
<pre class="language-text"><code class="language-text">npm i  -g http-server<br>http-server [path]</code></pre>
<p>Quickly serve a directory through localhost:8080 with zero-config.</p>
<h3><a href="https://www.npmjs.com/package/netlify-cli">netlify-cli</a></h3>
<pre class="language-text"><code class="language-text">npm i -g netlify-cli<br>netlify deploy</code></pre>
<p>Deploy a site to Netlify from the command line. I'll use this to deploy temporary site when I need to demo work in progress.</p>
<h3><a href="https://www.npmjs.com/package/nodemon">nodemon</a></h3>
<pre class="language-text"><code class="language-text">npm i -g nodemon<br>nodemon app.js</code></pre>
<p>This will run your code in Node and automatically restart if it detects any files changes in the directory. Great to have installed globally for quick scripts.</p>
<h3><a href="https://www.npmjs.com/package/sort-package-json">sort-package-json</a></h3>
<pre class="language-text"><code class="language-text">npm i -g sort-package-json<br>sort-package-json</code></pre>
<p>Predictably, this sorts the package.json of your current directory. Tidy package.json, tidy mind.</p>
<h3><a href="https://www.npmjs.com/package/fkill-cli">fkill-cli</a></h3>
<pre class="language-text"><code class="language-text">npm i -g fkill-cli<br>fkill node --force</code></pre>
<p>Cross-platform process killer. Useful when you have node running in the background and you've closed the terminal window that started it.</p>
<h3><a href="https://www.npmjs.com/package/concurrently">concurrently</a></h3>
<pre class="language-text"><code class="language-text">npm i -g concurrently<br>concurrently "command1 arg" "command2 arg"</code></pre>
<p>Run multiple commands concurrently.</p>
<h3>List globally installed packages</h3>
<p>Run this command to see what you have installed globally.</p>
<p><code>npm ls -g --depth=0</code></p>

    ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Favourite films of 2010&#39;s</title>
            <link href="https://www.belter.io/films-2010/"/>
            <updated>2019-11-12T00:00:00Z</updated>
            <id>https://www.belter.io/films-2010/</id>
            <content type="html">
                <![CDATA[
      <style>

.rating {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-direction: row;
    margin-left: 1rem;
}

.imdb {
    width: 2rem;
}

</style>
<p>Now that the decade is coming to a close and &quot;top <em>x</em> of the decade&quot; lists are popping up everywhere, I thought I'd add to the pile with my favourite movies of the last 10 years.</p>
<table>
<thead>
<tr>
<th>Film</th>
<th>Year</th>
<th><img src="/images/imdb.svg" alt="IMDB" class="imdb" /></th>
</tr>
</thead>
<tbody>
<tr>
<td>Baby Driver</td>
<td>2017</td>
<td>7.6</td>
</tr>
<tr>
<td>Coherence</td>
<td>2013</td>
<td>7.2</td>
</tr>
<tr>
<td>Deadpool</td>
<td>2016</td>
<td>8.0</td>
</tr>
<tr>
<td>Dunkirk</td>
<td>2017</td>
<td>7.9</td>
</tr>
<tr>
<td>Edge of Tomorrow</td>
<td>2014</td>
<td>7.9</td>
</tr>
<tr>
<td>Ex Machina</td>
<td>2014</td>
<td>7.7</td>
</tr>
<tr>
<td>Get Out</td>
<td>2017</td>
<td>7.7</td>
</tr>
<tr>
<td>Gone Girl</td>
<td>2014</td>
<td>8.1</td>
</tr>
<tr>
<td>Inception</td>
<td>2010</td>
<td>8.8</td>
</tr>
<tr>
<td>Moonrise Kingdom</td>
<td>2012</td>
<td>7.8</td>
</tr>
<tr>
<td>Scott Pilgrim vs The World</td>
<td>2010</td>
<td>7.5</td>
</tr>
<tr>
<td>Shutter Island</td>
<td>2010</td>
<td>8.1</td>
</tr>
<tr>
<td>Skyfall</td>
<td>2012</td>
<td>7.7</td>
</tr>
<tr>
<td>Spider-Man: Into the Spider-Verse</td>
<td>2018</td>
<td>8.4</td>
</tr>
<tr>
<td>Star Wars: The Force Awakens</td>
<td>2015</td>
<td>7.9</td>
</tr>
<tr>
<td>The Social Network</td>
<td>2010</td>
<td>7.7</td>
</tr>
<tr>
<td>The Wolf of Wall Street</td>
<td>2013</td>
<td>8.2</td>
</tr>
<tr>
<td>Whiplash</td>
<td>2014</td>
<td>8.5</td>
</tr>
<tr>
<td>Wind River</td>
<td>2017</td>
<td>7.7</td>
</tr>
</tbody>
</table>

    ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Dark Mode CSS with the prefers-color-scheme media query</title>
            <link href="https://www.belter.io/dark-mode-css/"/>
            <updated>2019-12-04T00:00:00Z</updated>
            <id>https://www.belter.io/dark-mode-css/</id>
            <content type="html">
                <![CDATA[
      <p><strong>prefers-color-scheme</strong> is a new-ish CSS media query that lets developers define styles tailored to a visitor's color scheme system setting.</p>
<p><code>@media (prefers-color-scheme: light|dark|no-preference) { ... }</code></p>
<p>Picture a webpage with a white background with mostly black text. If a visitor has their operating system's colour scheme set to Dark, a few line of CSS is all that's needed to make the website fall in line.</p>
<pre class="language-css"><code class="language-css"><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">prefers-color-scheme</span><span class="token punctuation">:</span> dark<span class="token punctuation">)</span></span> <span class="token punctuation">{</span><br>  <span class="token selector">body</span> <span class="token punctuation">{</span><br>    <span class="token property">background</span><span class="token punctuation">:</span> #000<span class="token punctuation">;</span><br>    <span class="token property">color</span><span class="token punctuation">:</span> #ccc<span class="token punctuation">;</span><br>  <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<h3>Browser Support</h3>
<a href="http://caniuse.com/#feat=prefers-color-scheme">
<picture>
<source type="image/webp" srcset="https://caniuse.bitsofco.de/image/prefers-color-scheme.webp">
<img src="https://caniuse.bitsofco.de/image/prefers-color-scheme.png" alt="Data on support for the prefers-color-scheme feature across the major browsers from caniuse.com">
</picture>
</a>
<h3>Resources</h3>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme">MDN Article</a></li>
</ul>

    ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Add Git-Bash to the new Windows Terminal</title>
            <link href="https://www.belter.io/add-git-bash-to-windows-terminal/"/>
            <updated>2019-12-08T00:00:00Z</updated>
            <id>https://www.belter.io/add-git-bash-to-windows-terminal/</id>
            <content type="html">
                <![CDATA[
      <p>I installed the new <a href="https://www.microsoft.com/store/productId/9N0DX20HK701">Windows Terminal (Preview)</a> from the Microsoft Store over the weekend. It allows you to create tabs for all variety of shells. By default the list of options are Windows Powershell, cmd and Azure Cloud Shell.</p>
<p><img src="/images/tabs.png" alt="tab options"></p>
<p>Git-Bash is installed as part of <a href="https://gitforwindows.org/">Git for Windows</a> so I'd like to add this to the list and set is as the default shell.</p>
<p>Open settings with <code>Ctrl+,</code> or via the little down arrow. This will open profiles.json in your preferred text-editor.</p>
<p>Add the following to the profiles []. Set guid to something unique.</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span><br>   <span class="token property">"guid"</span><span class="token operator">:</span> <span class="token string">"{abc00000-0000-0000-0000-000000000000}"</span><span class="token punctuation">,</span><br>   <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"Git-Bash"</span><span class="token punctuation">,</span><br>   <span class="token property">"commandline"</span><span class="token operator">:</span> <span class="token string">"%PROGRAMFILES%\\Git\\bin\\bash.exe"</span><span class="token punctuation">,</span><br>   <span class="token property">"icon"</span><span class="token operator">:</span> <span class="token string">"%PROGRAMFILES%\\Git\\mingw64\\share\\git\\git-for-windows.ico"</span><span class="token punctuation">,</span><br>   <span class="token property">"startingDirectory"</span> <span class="token operator">:</span> <span class="token string">"~"</span><br><span class="token punctuation">}</span><span class="token punctuation">,</span></code></pre>
<p>Save profiles.json and Terminal should now display Git-Bash in the choice of tabs.</p>
<p><img src="/images/tabs_updated.png" alt="tab options with Git-Bash"></p>
<h3>Setting to default</h3>
<p>To set Git-Bash as the default rather than Powershell, replace the defaultProfile value with your Git-Bash guid.</p>
<p><code>&quot;defaultProfile&quot; : &quot;{abc00000-0000-0000-0000-000000000000}&quot;,</code></p>

    ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Better filenames for React Suspense/Lazy chunks</title>
            <link href="https://www.belter.io/react-suspense-lazy-chunk-filenames/"/>
            <updated>2019-12-08T00:00:00Z</updated>
            <id>https://www.belter.io/react-suspense-lazy-chunk-filenames/</id>
            <content type="html">
                <![CDATA[
      <p><a href="https://reactjs.org/docs/code-splitting.html">React Suspense</a> allows you to easily add code-splitting into your application by lazy loading certain components, replacing them with something else until they've download.</p>
<p>Before code-splitting, your webpack build might generate a single file for all of your application code.</p>
<p>Imagine a React application with multiple pages and components. One of these pages is MyPage.</p>
<pre class="language-jsx"><code class="language-jsx"><span class="token keyword">import</span> React <span class="token keyword">from</span> <span class="token string">"react"</span><span class="token punctuation">;</span><br><span class="token keyword">import</span> HeavyComponent <span class="token keyword">from</span> <span class="token string">"./HeavyComponent"</span><span class="token punctuation">;</span><br><br><span class="token keyword">const</span> <span class="token function-variable function">MyPage</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span><br>  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">></span></span><span class="token plain-text"><br>    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>h1</span><span class="token punctuation">></span></span><span class="token plain-text">I am the page</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>h1</span><span class="token punctuation">></span></span><span class="token plain-text"><br>    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">HeavyComponent</span></span> <span class="token punctuation">/></span></span><span class="token plain-text"><br>  </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span><br><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token keyword">export</span> <span class="token keyword">default</span> MyPage<span class="token punctuation">;</span></code></pre>
<p>Let's lazy load the <code>HeavyComponent</code> so it's code isn't downloaded by the browser until a visitor hits <code>MyPage</code> for the first time.</p>
<pre class="language-jsx"><code class="language-jsx"><span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> Suspense<span class="token punctuation">,</span> lazy <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react'</span><span class="token punctuation">;</span><br><br><span class="token keyword">const</span> HeavyComponent <span class="token operator">=</span> <span class="token function">lazy</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token keyword">import</span><span class="token punctuation">(</span><span class="token string">'./HeavyComponent'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token keyword">const</span> <span class="token function-variable function">MyPage</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span><br>  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">></span></span><span class="token plain-text"><br>    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>h1</span><span class="token punctuation">></span></span><span class="token plain-text">I am the page</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>h1</span><span class="token punctuation">></span></span><span class="token plain-text"><br>    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">Suspense</span></span> <span class="token attr-name">fallback</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span><span class="token plain-text">Loading...</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span><span class="token punctuation">}</span></span><span class="token punctuation">></span></span><span class="token plain-text"><br>       </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">HeavyComponent</span></span> <span class="token punctuation">/></span></span><span class="token plain-text"><br>    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token class-name">Suspense</span></span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span><br><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token keyword">export</span> <span class="token keyword">default</span> MyPage<span class="token punctuation">;</span></code></pre>
<p>HeavyComponent now gets split into a seperate chunk with a numbered filename in your build directory e.g. 1.js</p>
<h3>Better filenames with webpackChunkName</h3>
<p>1.js isn't a very helpful filename. Fortunately with <code>webpackChunkName</code> in an inline comment, we can instruct webpack to name the file something much friendlier.</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> HeavyComponent <span class="token operator">=</span> <span class="token function">lazy</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token keyword">import</span><span class="token punctuation">(</span><span class="token comment">/* webpackChunkName: "HeavyComponent" */</span> <span class="token string">'./HeavyComponent'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Now the chunk will be named HeavyComponent.js</p>

    ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>My Web Development Setup</title>
            <link href="https://www.belter.io/uses/"/>
            <updated>2020-01-15T00:00:00Z</updated>
            <id>https://www.belter.io/uses/</id>
            <content type="html">
                <![CDATA[
      <p>The following is a my work setup as of August 2024.</p>
<h3>🖋️ Editor</h3>
<ul>
<li><a href="https://code.visualstudio.com/">Visual Studio Code</a> with a giant pile of <a href="https://howivscode.com/duncanmcdougall">extensions</a>.</li>
<li>Theme: <a href="https://marketplace.visualstudio.com/itemdetails?itemName=zhuangtongfa.Material-theme">One Dark Pro Vivid</a>.</li>
<li>Font: <a href="https://www.jetbrains.com/lp/mono/">Jetbrains Mono</a>. Ligatures all the way.</li>
</ul>
<h3>⌨ Terminal</h3>
<ul>
<li><a href="https://www.warp.dev">Warp</a>. Great auto-completion, workspaces, and a bunch of AI I don't use.</li>
<li><a href="https://ohmyposh.dev/">Oh-my-posh</a>adds some nice theming.</li>
<li><a href="/npm-global-packages">NPM packages I install globally</a>.</li>
<li>For Node, I use NVM autoloading. When I navigate into different repos, nvm will automatically switch the active version of node based on the .nvmrc file.</li>
</ul>
<h3>📁 Desktop Apps</h3>
<ul>
<li>I'm back on a Mac after too much fighting with Windows.</li>
<li>Chrome. I've tried Arc, but it didn't stick.</li>
<li><a href="https://notepad.belter.io/">My Notepad PWA</a> or Notion for daily note taking, to-do lists and planning small projects.</li>
<li><a href="https://www.figma.com/">Figma</a> for UI design.</li>
<li><a href="https://www.getpostman.com/">Postman</a> to test and debugging APIs.</li>
<li><a href="https://www.jetbrains.com/datagrip/">DataGrip</a>. &quot;Many databases, one tool&quot;</li>
<li><a href="https://affinity.serif.com/en-gb/photo/">Affinity Photo</a> is my Photoshop/Lightroom.</li>
<li><a href="https://www.docker.com/products/docker-desktop">Docker Desktop</a>.</li>
<li><a href="https://rectangleapp.com/">Rectangle</a> for window resizing. Why do I need this??</li>
<li>Teams, Spotify</li>
<li>Excalidraw for quick diagrams and scribbles when screensharing.</li>
<li><a href="https://www.trymeeter.com/">Meeter</a> - Joining my next meeting is one click from the MenuBar.</li>
</ul>
<h3>🕸️ Web Apps &amp; Services</h3>
<ul>
<li><a href="https://gsuite.google.co.uk/intl/en_uk/">G Suite</a> give me the best of GMail, Drive and co for my business.</li>
<li><a href="https://www.github.com/duncanmcdougall">GitHub</a> for code.</li>
<li>My projects are split between Vercel and Netlify</li>
<li><a href="https://svgomg.firebaseapp.com/">SVGOMG</a> - UI for optimising SVGs. Installed as a PWA.</li>
</ul>
<h3>🔩 Hardware</h3>
<ul>
<li>Macbook Pro M2 15inch which I connect to a <a href="https://www.caldigit.com/ts3-plus/">CalDigit dock</a> when I'm at my desk. One cable for everything is so nice.</li>
<li>Logitech MX Master v1 mouse. I'm a lifer now. I'll replace/repair this thing until retirement.</li>
<li><a href="https://www.keychron.com/products/keychron-k2-wireless-mechanical-keyboard">Keychron K2</a>. I went mechanical and ditched the numpad in the process. Less twisting at the elbow for the mouse == more comfort. Believe the hype.</li>
<li>A 34-inch LG UltraWide monitor.</li>
<li>Google Pixel 8. It's fine.</li>
<li>Bose QuietComfort 45 noise-cancelling headphones.</li>
<li>There's a couple of Raspberry Pis and Arduinos gathering dust somewhere.</li>
</ul>
<p>If you like this kind of content, check out <a href="https://uses.tech/">uses.tech</a> for more developer's setups.</p>

    ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Run Umbraco from VS Code</title>
            <link href="https://www.belter.io/umbraco-vscode/"/>
            <updated>2020-01-23T00:00:00Z</updated>
            <id>https://www.belter.io/umbraco-vscode/</id>
            <content type="html">
                <![CDATA[
      <p>Probably the quickest, leanest way to get to work on a fresh Umbraco site is with VSCode and IIS Express.</p>
<p><img src="/images/umbraco-dashboard.png" alt="Umbraco dashboard"></p>
<ol>
<li>Install <a href="https://www.microsoft.com/en-us/download/details.aspx?id=48264">IIS Express</a></li>
<li>In VSCode, install the <a href="https://marketplace.visualstudio.com/items?itemName=warren-buckley.iis-express">IIS Express extension</a> by Warren Buckley.</li>
<li><a href="https://our.umbraco.com/download/">Download Umbraco</a> and unzip.</li>
<li>Open your new Umbraco folder in VSCode</li>
<li>Start the website with <code>Ctrl+F5</code> or selecting <code>IIS Express: Start Website</code> from command pallete</li>
</ol>
<p>Once you've ran through in the install wizard you're good to go.</p>

    ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Podcasts I&#39;m listening to</title>
            <link href="https://www.belter.io/podcasts-playlist/"/>
            <updated>2020-01-24T00:00:00Z</updated>
            <id>https://www.belter.io/podcasts-playlist/</id>
            <content type="html">
                <![CDATA[
      <p>The #1 question in the world right now.</p>
<blockquote>
    What podcasts are you listening to?
</blockquote>
<h3>🕸 <a href="https://syntax.fm/">Syntax.fm</a></h3>
<p>A twice weekly &quot;Tasty Treats Podcast for Web Developers.&quot;</p>
<p>Top Episode: <a href="https://syntax.fm/show/138/what-s-new-in-web-development">What's new in web development</a></p>
<h3>🕸 <a href="https://shoptalkshow.com/">Shop Talk Show</a></h3>
<p>Development, design, performance, accessibility, tooling, a little bit of everything!</p>
<p>Top Episode: <a href="https://shoptalkshow.com/episodes/375/">Greenfield</a></p>
<h3>⚽ <a href="https://www.bbc.co.uk/programmes/p06kyljg/episodes/downloads">That Peter Crouch Podcast</a></h3>
<p>Hilarious guide to being a professional footballer by the big man himself.</p>
<p>Top Episode: <a href="https://www.bbc.co.uk/programmes/p080d4qz">That Holidays Episode</a></p>
<h3>🎬 <a href="https://www.theringer.com/the-rewatchables">The Rewatchables</a></h3>
<p>A roundtable movie podcast on some of the most rewatchable movies ever made.</p>
<p>Top Episode: <a href="https://www.theringer.com/2019/8/13/20803917/gone-girl-with-bill-simmons-shea-serrano-mallory-rubin-and-sean-fennessey">Gone Girl</a></p>
<h3>🎙 <a href="https://play.acast.com/s/lukeandpete">The Luke and Peter Show</a></h3>
<p>Two lads having an unplanned chat about everything and anything.</p>
<p>Top Episode: <a href="https://play.acast.com/s/lukeandpete/e08eea42-3413-4e57-a724-3dedb78a0ebd">The Curse of the Colonel</a></p>
<h3>⚽ <a href="https://play.acast.com/s/footballramble">The Football Ramble</a></h3>
<p>Five episodes a week covering previews and reviews of the weeks action.</p>

    ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>The prefers-reduced-motion media query</title>
            <link href="https://www.belter.io/prefers-reduced-motion/"/>
            <updated>2020-01-25T00:06:18Z</updated>
            <id>https://www.belter.io/prefers-reduced-motion/</id>
            <content type="html">
                <![CDATA[
      <p>The <code>prefers-reduced-motion</code> media feature is used to detect if the user has requested that the system minimizes the amount of animation or motion on the page.</p>
<p><code>Value: no-preference | reduce</code></p>
<pre class="language-css"><code class="language-css"><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">prefers-reduced-motion</span><span class="token punctuation">:</span> reduce<span class="token punctuation">)</span></span> <span class="token punctuation">{</span><br>  <span class="token comment">/* disable off your motion */</span><br><span class="token punctuation">}</span><br><br><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">prefers-reduced-motion</span><span class="token punctuation">:</span> no-preference<span class="token punctuation">)</span></span> <span class="token punctuation">{</span><br>  <span class="token comment">/* Or enable animations */</span><br><span class="token punctuation">}</span></code></pre>
<h3>Changing your device settings</h3>
<p>You should find a setting for this in the accessibility settings in recent versions of Android, iOS, macOS, and Windows.</p>
<p>For Android: Settings -&gt; Accessibility -&gt; Remove animations</p>
<p>For iOS: Settings -&gt; Accessibility -&gt; Vision -&gt; Motion -&gt; Reduce motion</p>
<p><img src="/images/motion.jpg" alt="Motion settings"></p>
<h3>CSS</h3>
<p>From Andy Bell's <a href="https://hankchizljaw.com/wrote/a-modern-css-reset/">A Modern CSS Reset</a></p>
<pre class="language-css"><code class="language-css"><span class="token comment">/* Remove all animations and transitions for people that prefer not to see them */</span><br><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">prefers-reduced-motion</span><span class="token punctuation">:</span> reduce<span class="token punctuation">)</span></span> <span class="token punctuation">{</span><br>  <span class="token selector">*</span> <span class="token punctuation">{</span><br>    <span class="token property">animation-duration</span><span class="token punctuation">:</span> 0.01ms <span class="token important">!important</span><span class="token punctuation">;</span><br>    <span class="token property">animation-iteration-count</span><span class="token punctuation">:</span> 1 <span class="token important">!important</span><span class="token punctuation">;</span><br>    <span class="token property">transition-duration</span><span class="token punctuation">:</span> 0.01ms <span class="token important">!important</span><span class="token punctuation">;</span><br>    <span class="token property">scroll-behavior</span><span class="token punctuation">:</span> auto <span class="token important">!important</span><span class="token punctuation">;</span><br>  <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<h3>Demo</h3>
<p>If the browser find your OS setting set to reduce motion, the cartwheeler below should not be spinning.</p>
<style>
  @keyframes prefers-reduced-motion-test {
    from {
      transform: rotate(0deg);
    }
    to {
      transform: rotate(360deg);
    }
  }

  .prefers-reduced-motion-test {
    margin: 1rem 0;
    animation: prefers-reduced-motion-test infinite 3s ease;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 3rem;
  }
</style>
<div class="prefers-reduced-motion-test">
🤸‍♀️</div>
<h3>Browser Support</h3>
<a href="http://caniuse.com/#feat=prefers-reduced-motion">
<picture>
<source type="image/webp" srcset="https://caniuse.bitsofco.de/image/prefers-reduced-motion.webp">
<img src="https://caniuse.bitsofco.de/image/prefers-reduced-motion.png" alt="Data on support for the prefers-reduced-motion feature across the major browsers from caniuse.com">
</picture>
</a>
<h3>Further Reading</h3>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion">MDN Article</a></li>
</ul>

    ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>My Eleventy + SCSS/SASS Setup</title>
            <link href="https://www.belter.io/eleventy-sass-workflow/"/>
            <updated>2020-01-30T00:00:00Z</updated>
            <id>https://www.belter.io/eleventy-sass-workflow/</id>
            <content type="html">
                <![CDATA[
      <p>This week's train project has been to convert this site from <a href="https://www.gatsbyjs.org/">Gatsby</a> to <a href="https://www.11ty.dev/">Eleventy (11ty)</a>. Gatsby still has a place in my toolkit but for this site I've found 11ty has the flexibility to quickly and simply shape pages in unique ways.</p>
<p>Eleventy doesn't have out-of-the-box SCSS/SASS pre-processing so it's up to you to bring in your own process. Taking inspiration from the excellent <a href="https://hylia.website/">Hylia starter kit</a> here's how I do it with a just a few npm scripts.</p>
<h3>Install Dependencies</h3>
<pre class="language-text"><code class="language-text">npm i --save sass<br>npm i --save-dev npm-run-all</code></pre>
<h3>NPM scripts</h3>
<p>My package.json file has 5 commands defined in the scripts section. Luckily I only ever need to run <code>npm start</code> directly.</p>
<h4>Compile the .scss</h4>
<p><code>npm run sass</code> compiles the root .scss into a .css file in the _includes directory</p>
<pre class="language-json"><code class="language-json"><span class="token property">"sass"</span><span class="token operator">:</span> <span class="token string">"sass --style=compressed src/scss/styles.scss src/_includes/css/styles.css"</span><span class="token punctuation">,</span></code></pre>
<p>I'm using nunjucks for templating so I inject the CSS in my base.njk template.</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>style</span><span class="token punctuation">></span></span><span class="token style"><span class="token language-css"><br>  <span class="token punctuation">{</span>% include <span class="token string">"css/styles.css"</span> ignore missing %<span class="token punctuation">}</span><br></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>style</span><span class="token punctuation">></span></span></code></pre>
<h4>Running 11ty locally</h4>
<p>Running <code>npm start</code> spins up the site on http://localhost:8080 and auto-reload whenever any of my code changes.</p>
<ol>
<li>Start eleventy in serve mode and reload the page whenever anything changes in src.</li>
<li>Watch for changes to .scss files and recompiles my styles.</li>
<li>Run both in parallel with <code>npm start</code></li>
</ol>
<pre class="language-json"><code class="language-json"><span class="token property">"watch:eleventy"</span><span class="token operator">:</span> <span class="token string">"eleventy --serve"</span><span class="token punctuation">,</span><br><span class="token property">"watch:sass"</span><span class="token operator">:</span> <span class="token string">"npm run sass -- --watch"</span><br><span class="token property">"start"</span><span class="token operator">:</span> <span class="token string">"npm-run-all sass --parallel watch:*"</span></code></pre>
<h4>Build for Production</h4>
<p><code>npm run build</code> compiles CSS and builds the entire project into the output directory. Netlify runs this command on any new commit to the master branch.</p>
<pre class="language-json"><code class="language-json"><span class="token property">"build"</span><span class="token operator">:</span> <span class="token string">"npm run sass &amp;&amp; eleventy"</span></code></pre>
<h3>Gotchas</h3>
<h4>.gitignore the compiled CSS</h4>
<p>By default,anything listed in .gitignore or .eleventyignore will be ignored by eleventy's watch process. If the compiled CSS is ignored, eleventy --serve wouldn't rebuild of the html whenever your sass is recompiled.</p>
<p>Luckily, there's a workaround. You can opt-out of eleventy inspecting .gitignore with the following</p>
<pre class="language-js"><code class="language-js">module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">eleventyConfig</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br>  eleventyConfig<span class="token punctuation">.</span><span class="token function">setUseGitIgnore</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>

    ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Create a Sitemap.xml with Eleventy</title>
            <link href="https://www.belter.io/eleventy-sitemap/"/>
            <updated>2020-02-06T23:00:00Z</updated>
            <id>https://www.belter.io/eleventy-sitemap/</id>
            <content type="html">
                <![CDATA[
      <p>Sitemaps are an underrated tool for helping search engines crawl into every corner of your website. Fortunately building an XML sitemap in Eleventy (11ty) like <a href="/sitemap.xml">this one</a> is super quick and easy.</p>
<p><a href="https://github.com/duncanmcdougall/eleventy-sitemap-demo">Demo on GitHub</a></p>
<p>Start by creating <code>sitemap.njk</code> in your source directory.</p>
<pre class="language-xml"><code class="language-xml">---<br>permalink: /sitemap.xml<br>eleventyExcludeFromCollections: true<br>---<br><span class="token prolog">&lt;?xml version="1.0" encoding="utf-8"?></span><br><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>urlset</span> <span class="token attr-name">xmlns</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>http://www.sitemaps.org/schemas/sitemap/0.9<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br>    {% for page in collections.all %}<br>       {% if not page.data.draft %}<br>        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>url</span><span class="token punctuation">></span></span><br>            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>loc</span><span class="token punctuation">></span></span>{{ site.url }}{{ page.url | url }}<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>loc</span><span class="token punctuation">></span></span><br>            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>lastmod</span><span class="token punctuation">></span></span>{{ page.date.toISOString() }}<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>lastmod</span><span class="token punctuation">></span></span><br>            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>changefreq</span><span class="token punctuation">></span></span>{{ page.data.changeFreq if page.data.changeFreq else "monthly" }}<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>changefreq</span><span class="token punctuation">></span></span><br>        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>url</span><span class="token punctuation">></span></span><br>        {% endif %}<br>    {% endfor %}<br><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>urlset</span><span class="token punctuation">></span></span><br></code></pre>
<h3>Let's take a closer look at a few lines...</h3>
<h4>Global Data</h4>
<p><code>&lt;loc&gt;{{ site.url }}{{ page.url | url }}&lt;/loc&gt;</code></p>
<p>While we could always hardcode our domain, it's a nice idea to lean on 11ty's <a href="https://www.11ty.dev/docs/data-global/">global data</a> and pull it from there. My global JSON file is at <code>src/_data/site.json</code>. Now &quot;https://www.belter.io&quot; is prepended to each page's path.</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span><br>  <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"Duncan McDougall"</span><span class="token punctuation">,</span><br>  <span class="token property">"url"</span><span class="token operator">:</span> <span class="token string">"https://www.belter.io"</span><span class="token punctuation">,</span><br>  ...<br><span class="token punctuation">}</span></code></pre>
<h4>changefreq</h4>
<p><code>&lt;changefreq&gt;{{ page.data.changeFreq if page.data.changeFreq else &quot;monthly&quot; }}&lt;/changefreq&gt;</code></p>
<p>There are some pages that change more frequently than others and it's worth hinting to search engines that you'd like them to recrawl these pages more often. Achieve this by adding a changefreq value to these page's <a href="https://www.11ty.dev/docs/data-frontmatter/">front matter data</a>.</p>
<p>Valid values are:</p>
<ul>
<li>always</li>
<li>hourly</li>
<li>daily</li>
<li>weekly</li>
<li>monthly</li>
<li>yearly</li>
<li>never</li>
</ul>
<p>As I've been evolving this site quite a bit recently, I've set my homepage's changefreq to daily.</p>
<h3>Letting the bots know</h3>
<p>Once you have a working sitemap, your next steps should be let search engines know where to find it. The simplest way is to add a reference in your robots.txt file.</p>
<pre class="language-text"><code class="language-text">Sitemap: https://www.belter.io/sitemap.xml<br><br>User-agent: *<br>Disallow:</code></pre>
<p>You can then point Google there with <a href="https://search.google.com/search-console/about">Search Console</a>.</p>

    ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Add Search to an Eleventy website with Elasticlunr</title>
            <link href="https://www.belter.io/eleventy-search/"/>
            <updated>2020-02-12T23:45:00Z</updated>
            <id>https://www.belter.io/eleventy-search/</id>
            <content type="html">
                <![CDATA[
      <p>I recently found out about <a href="http://elasticlunr.com/">Elasticlunr</a>, a lightweight, full-text search engine built in JavaScript. It got me thinking how this could be integrated into an eleventy site for client-side search. It's pretty easy as it happens.</p>
<ul>
<li><a href="https://github.com/duncanmcdougall/eleventy-search-demo">Demo GitHub repo</a></li>
<li><a href="https://elasticlunr-11ty.netlify.com/">Demo site</a></li>
<li><a href="/search">Search this site</a></li>
</ul>
<p>I have a collection of 100 markdown documents, each about a different movie. Their frontmatter data has a title, excerpt, and a list of genres. This is what we'll add to the index.</p>
<pre class="language-text"><code class="language-text">---<br>title: "Parasite"<br>excerpt: "All unemployed, Ki-taek's family takes peculiar interest in the wealthy and glamorous Parks for their livelihood until they get entangled in an unexpect..."<br>genres:<br>  - Comedy<br>  - Drama<br>  - Thriller<br>---</code></pre>
<h3>Building an index</h3>
<p>We're going to create an 11ty filter. We'll use this to convert our movies collection into an elasticlunr index which will be output as JSON with the url <code>/search-index.json</code></p>
<h4>src/filters/searchFilter.js</h4>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">const</span> elasticlunr <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"elasticlunr"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">collection</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br>  <span class="token comment">// what fields we'd like our index to consist of</span><br>  <span class="token keyword">var</span> index <span class="token operator">=</span> <span class="token function">elasticlunr</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br>    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">addField</span><span class="token punctuation">(</span><span class="token string">"title"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">addField</span><span class="token punctuation">(</span><span class="token string">"excerpt"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">addField</span><span class="token punctuation">(</span><span class="token string">"genres"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setRef</span><span class="token punctuation">(</span><span class="token string">"id"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>  <span class="token comment">// loop through each page and add it to the index</span><br>  collection<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">page</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br>    index<span class="token punctuation">.</span><span class="token function">addDoc</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br>      <span class="token literal-property property">id</span><span class="token operator">:</span> page<span class="token punctuation">.</span>url<span class="token punctuation">,</span><br>      <span class="token literal-property property">title</span><span class="token operator">:</span> page<span class="token punctuation">.</span>template<span class="token punctuation">.</span>frontMatter<span class="token punctuation">.</span>data<span class="token punctuation">.</span>title<span class="token punctuation">,</span><br>      <span class="token literal-property property">excerpt</span><span class="token operator">:</span> page<span class="token punctuation">.</span>template<span class="token punctuation">.</span>frontMatter<span class="token punctuation">.</span>data<span class="token punctuation">.</span>excerpt<span class="token punctuation">,</span><br>      <span class="token literal-property property">genres</span><span class="token operator">:</span> page<span class="token punctuation">.</span>template<span class="token punctuation">.</span>frontMatter<span class="token punctuation">.</span>data<span class="token punctuation">.</span>genres<span class="token punctuation">,</span><br>    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>  <span class="token keyword">return</span> index<span class="token punctuation">.</span><span class="token function">toJSON</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<h4>.eleventy.js</h4>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">const</span> searchFilter <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"./src/filters/searchFilter"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">config</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br>  <span class="token operator">...</span><br>  config<span class="token punctuation">.</span><span class="token function">addFilter</span><span class="token punctuation">(</span><span class="token string">"search"</span><span class="token punctuation">,</span> searchFilter<span class="token punctuation">)</span><span class="token punctuation">;</span><br>  config<span class="token punctuation">.</span><span class="token function">addCollection</span><span class="token punctuation">(</span><span class="token string">"movies"</span><span class="token punctuation">,</span> <span class="token parameter">collection</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br>    <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token operator">...</span>collection<span class="token punctuation">.</span><span class="token function">getFilteredByGlob</span><span class="token punctuation">(</span><span class="token string">"./src/movies/**/*.md"</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br>  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>  <span class="token operator">...</span><br><span class="token punctuation">}</span><span class="token punctuation">;</span><br></code></pre>
<h4>search-index.json.njk</h4>
<pre class="language-text"><code class="language-text">---<br>permalink: /search-index.json<br>---<br><br>{{ collections.movies | search | dump | safe }}</code></pre>
<h3>Search Page</h3>
<p>Now we have an index, let's use it on a page with just HTML and a little JavaScript. With the code below, we're instructing the browser to fetch search-index.json, load it into elasticlunr, search it, and finally add the results to an <code>&lt;ol&gt;</code> element.</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>field<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br>  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>label</span> <span class="token attr-name">for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>searchField<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Search<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>label</span><span class="token punctuation">></span></span><br>  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>search<span class="token punctuation">"</span></span> <span class="token attr-name">placeholder</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Search...<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>searchField<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>ol</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>searchResults<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>noResultsFound<span class="token punctuation">"</span></span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">display</span><span class="token punctuation">:</span> none</span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span><br>  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>No results found.<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span><br><span class="token comment">&lt;!--Only 5.7kb GZipped. You may want to bundle this with your application code. --></span><br><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>https://cdnjs.cloudflare.com/ajax/libs/elasticlunr/0.9.6/elasticlunr.min.js<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">></span></span></code></pre>
<pre class="language-javascript"><code class="language-javascript"><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">window<span class="token punctuation">,</span> document</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br>  <span class="token string">"use strict"</span><span class="token punctuation">;</span><br><br>  <span class="token keyword">const</span> <span class="token function-variable function">search</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br>    <span class="token keyword">const</span> results <span class="token operator">=</span> window<span class="token punctuation">.</span>searchIndex<span class="token punctuation">.</span><span class="token function">search</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span>target<span class="token punctuation">.</span>value<span class="token punctuation">,</span> <span class="token punctuation">{</span><br>      <span class="token literal-property property">bool</span><span class="token operator">:</span> <span class="token string">"OR"</span><span class="token punctuation">,</span><br>      <span class="token literal-property property">expand</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span><br>    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>    <span class="token keyword">const</span> resEl <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">"searchResults"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>    <span class="token keyword">const</span> noResultsEl <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">"noResultsFound"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>    resEl<span class="token punctuation">.</span>innerHTML <span class="token operator">=</span> <span class="token string">""</span><span class="token punctuation">;</span><br>    <span class="token keyword">if</span> <span class="token punctuation">(</span>results<span class="token punctuation">)</span> <span class="token punctuation">{</span><br>      noResultsEl<span class="token punctuation">.</span>style<span class="token punctuation">.</span>display <span class="token operator">=</span> <span class="token string">"none"</span><span class="token punctuation">;</span><br>      results<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">r</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br>        <span class="token keyword">const</span> <span class="token punctuation">{</span> id<span class="token punctuation">,</span> title<span class="token punctuation">,</span> description <span class="token punctuation">}</span> <span class="token operator">=</span> r<span class="token punctuation">.</span>doc<span class="token punctuation">;</span><br>        <span class="token keyword">const</span> el <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">"li"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>        resEl<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>el<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>        <span class="token keyword">const</span> h3 <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">"h3"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>        el<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>h3<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>        <span class="token keyword">const</span> a <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">"a"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>        a<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">"href"</span><span class="token punctuation">,</span> id<span class="token punctuation">)</span><span class="token punctuation">;</span><br>        a<span class="token punctuation">.</span>textContent <span class="token operator">=</span> title<span class="token punctuation">;</span><br>        h3<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>        <span class="token keyword">const</span> p <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">"p"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>        p<span class="token punctuation">.</span>textContent <span class="token operator">=</span> description<span class="token punctuation">;</span><br>        el<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>p<span class="token punctuation">)</span><span class="token punctuation">;</span><br>      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span><br>      noResultsEl<span class="token punctuation">.</span>style<span class="token punctuation">.</span>display <span class="token operator">=</span> <span class="token string">"block"</span><span class="token punctuation">;</span><br>    <span class="token punctuation">}</span><br>  <span class="token punctuation">}</span><span class="token punctuation">;</span><br><br>  <span class="token function">fetch</span><span class="token punctuation">(</span><span class="token string">"/search-index.json"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">response</span><span class="token punctuation">)</span> <span class="token operator">=></span><br>    response<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">rawIndex</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br>      window<span class="token punctuation">.</span>searchIndex <span class="token operator">=</span> elasticlunr<span class="token punctuation">.</span>Index<span class="token punctuation">.</span><span class="token function">load</span><span class="token punctuation">(</span>rawIndex<span class="token punctuation">)</span><span class="token punctuation">;</span><br>      document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">"searchField"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">"input"</span><span class="token punctuation">,</span> search<span class="token punctuation">)</span><span class="token punctuation">;</span><br>    <span class="token punctuation">}</span><span class="token punctuation">)</span><br>  <span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">(</span>window<span class="token punctuation">,</span> document<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h3>Final notes</h3>
<p>Keep in mind the number of pages in your collection and how much content your indexing. Since this is client-side search, the entire index will be downloaded by the browser. My demo site of 100 pages has an average of ~150 words indexed per page. The index is 26.5kb GZipped.</p>
<p>Once you've got search up and running it's worth checking out the <a href="http://elasticlunr.com/">ElasticLunr docs</a> and have a play with things like query-time boosting, boolean logic and token expansion.</p>
<p><a href="https://github.com/duncanmcdougall/eleventy-search-demo">View the full source code on GitHub</a></p>

    ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Quick Tip: npm outdated and npm update</title>
            <link href="https://www.belter.io/npm-outdated-update/"/>
            <updated>2020-11-07T00:00:00Z</updated>
            <id>https://www.belter.io/npm-outdated-update/</id>
            <content type="html">
                <![CDATA[
      <p>Use <code>npm outdate</code> and <code>npm update</code> to check for and update to newer versions of your installed node modules using npm's built-in commands.</p>
<h3><a href="https://docs.npmjs.com/cli/v6/commands/npm-outdated">npm outdated</a></h3>
<p><img src="/images/npm-outdated.png" alt="npm outdated"></p>
<ul>
<li><code>Current</code> is what you have installed</li>
<li><code>Wanted</code> is the latest version that satisfies the semver range in package.json</li>
<li><code>Latest</code> is, you guessed it, the latest.</li>
</ul>
<p>Red items mean the wanted version is also the latest.</p>
<h3><a href="https://docs.npmjs.com/cli/v6/commands/npm-update">npm update</a></h3>
<p>This will update all packages to the <code>wanted</code> version.</p>
<p>My package.json has <code>&quot;react&quot;: &quot;^16.13.1&quot;</code> listed as a dependency. <code>npm update</code> would change this to <code>&quot;react&quot;: &quot;^16.14.0&quot;,</code>, not v17.</p>
<p>Running <code>npm outdated</code> again would show I have every package updated the wanted version.</p>
<p><img src="/images/npm-outdated_2.png" alt="npm outdated after npm update"></p>
<p>Individual packages can be updated by listing the package names in the command e.g. <code>npm update react react-dom</code></p>
<h3>Updating to the latest and greatest</h3>
<p><code>npm update</code> only gets you as far as your semver range. If you want to break above that and get the latest, append <code>@latest</code> to the package name. e.g. <code>npm install react@latest</code></p>
<h3>Update Globally Installed Packages</h3>
<p>All three commands work globally with the addition of <code>-g</code> or <code>--global</code></p>
<pre class="language-text"><code class="language-text">npm outdated -g<br>npm update -g<br>npm install -g package@latest</code></pre>

    ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Creating better pull requests</title>
            <link href="https://www.belter.io/create-better-pull-requests/"/>
            <updated>2025-11-23T17:16:48Z</updated>
            <id>https://www.belter.io/create-better-pull-requests/</id>
            <content type="html">
                <![CDATA[
      <p>Pull requests: love them or hate them, they’re an essential part of collaborative development. Yet for many developers, they can be a frequent source of frustration. If you’ve worked on a project long enough, you’ve likely seen code review complaints crop up in sprint retrospectives, often revolving around the same recurring issues:</p>
<ul>
<li>Waiting too long for someone to review your PR.</li>
<li>The time commitment needed to review others’ PRs.</li>
<li>Endless back-and-forth debates over whether the code is &quot;good enough.&quot;</li>
</ul>
<p>It’s no surprise that code reviews can sometimes feel like a distraction from shipping features. But when done right, pull requests are more than just a necessary process—they’re a chance to collaborate, learn from each other, and improve the quality of your codebase.</p>
<p>In this post, I’ll share tips for creating pull requests that are easier to review, reduce friction, and boost team efficiency.</p>
<hr>
<h3>1. Start with a clear title</h3>
<p>Your PR title is the first thing reviewers see, so make it clear and concise.</p>
<p>👍 Fix login bug when using special characters<br/>
👎 login fix</p>
<p>Scanning through a list of PRs, a descriptive title helps reviewers quickly understand the purpose of your changes. It also makes it easier to search for and reference the PR later.</p>
<h3>2. Explain why this PR is necessary</h3>
<p>Link to the issue, user story, or design that this PR addresses. This helps reviewers quickly understand the purpose of the changes and why they’re necessary.</p>
<p>Providing this context isn’t just helpful for reviewers—it’s also invaluable for future developers. When someone stumbles upon this block of code six months down the line, they can trace it back to the original PR and the issue or story that inspired it.</p>
<h3>3. Summarize your changes</h3>
<p>Start your PR description with a brief summary of your changes, explaining your approach and reasoning. Highlight why you chose a specific method or design pattern to help reviewers provide better feedback.</p>
<blockquote>
<p>This PR implements a search bar component. I chose to debounce the API calls to minimize unnecessary requests. Let me know if the implementation feels too aggressive.&quot;</p>
</blockquote>
<p>A clear summary can also help catch mismatches between your explanation and the code, uncovering potential bugs early.</p>
<h3>4. Keep PRs small and focused</h3>
<p>Small, single-problem PRs are easier to review and merge. If you’re working on a large feature, break it into smaller, more manageable pieces.</p>
<p>Be explicit about what’s covered in the current PR and what will follow in subsequent ones.</p>
<p>For instance:</p>
<ul>
<li><em>This PR:</em> Implements the UI for the search bar.</li>
<li><em>Next PR:</em> Integrates the search bar with the backend API.</li>
</ul>
<h3>5. Add screenshots</h3>
<p>Show, don’t just tell! Adding screenshots, gifs, or videos of your changes makes it easier for reviewers to understand the impact of your work without needing to run the code.</p>
<p>For example, if you’ve worked on a front-end feature, include a screenshot of the updated UI. If it’s a backend feature, consider sharing the API response that demonstrates the change.</p>
<h3>6. Highlight areas for feedback</h3>
<p>If there are parts of the code where you’re uncertain, call them out in the PR. Reviewers appreciate being pointed to areas where their expertise or opinion is needed.</p>
<p>For example:</p>
<ul>
<li><em>&quot;I'm not sure if the error handling logic in <code>fetchData</code> is robust enough. Any suggestions?&quot;</em></li>
<li><em>&quot;Let me know if you think this CSS hack is too brittle—open to alternatives.&quot;</em></li>
</ul>
<p>This not only focuses reviewer attention but also demonstrates openness to collaboration.</p>
<h3>7. Automate where possible</h3>
<p>Leverage tools to reduce the manual effort for both authors and reviewers:</p>
<ul>
<li><strong>Pre-commit hooks</strong>: Automate linting and formatting before code is pushed.</li>
<li><strong>CI/CD pipelines</strong>: Ensure your PR passes tests and builds successfully before review.</li>
<li><strong>PR templates</strong>: Use templates to standardize PR descriptions, ensuring all key information is included.</li>
</ul>
<hr>
<p>By following these tips, you can make your pull requests a pleasure to review, foster better collaboration with your team, and improve the overall quality of your codebase. Remember, great pull requests save time for everyone—your future self included!</p>

    ]]>
            </content>
        </entry>
    
</feed>