<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[All your code are belong to us]]></title><description><![CDATA[Thoughts, stories and ideas on code and technology in general.<br>Blog title inspired by <a href="https://en.wikipedia.org/wiki/All_your_base_are_belong_to_us" target="_blank">this meme</a>]]></description><link>https://allurcode.com/</link><image><url>https://allurcode.com/favicon.png</url><title>All your code are belong to us</title><link>https://allurcode.com/</link></image><generator>Ghost 3.20</generator><lastBuildDate>Sat, 20 Jun 2020 21:01:23 GMT</lastBuildDate><atom:link href="https://allurcode.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Upgrade Raspbian from Jessie to Stretch]]></title><description><![CDATA[It's recommended to download a fresh image of Raspbian Stretch from official Raspbian website, but if for whatever reason you don't want to do that, you can still upgrade from Jessie to Stretch.]]></description><link>https://allurcode.com/upgrade-raspbian-from-jessie-to-stretch/</link><guid isPermaLink="false">5eee3275d0de6d0bbc10bc97</guid><category><![CDATA[Raspbian]]></category><dc:creator><![CDATA[Wojtek]]></dc:creator><pubDate>Sat, 20 Jun 2020 19:40:26 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>It's recommended to download a fresh image of Raspbian Stretch from official <a href="https://www.raspberrypi.org/downloads/">Raspbian website</a>, but if for whatever reason you don't want to do that, you can still upgrade from Jessie to Stretch.</p>
<h2 id="1diskspace">1. Disk space</h2>
<p>Check available disk space and make sure you have at least 1.5GB of free space.</p>
<pre><code class="language-bash">df -h
</code></pre>
<h2 id="2updatecurrentsystem">2. Update current system</h2>
<p>Before upgrading, make sure all your packages are up to date.</p>
<pre><code class="language-bash">sudo apt-get update
sudo apt-get upgrade
sudo apt-get dist-upgrade
</code></pre>
<h2 id="3updatepackagelists">3. Update package lists</h2>
<p>Update your package lists to use <code>Stretch</code> repositories. In both below files, change every occurrence of the word ‘jessie’ to ‘stretch’.</p>
<pre><code class="language-bash">vim.tiny /etc/apt/sources.list
vim.tiny /etc/apt/sources.list.d/raspi.list
</code></pre>
<h2 id="4updatepackages">4. Update packages</h2>
<p>Be aware this may take a while, depending on your internet connection and available resources. I'd say, around two hours.</p>
<pre><code class="language-bash">sudo apt-get update
#sudo apt-get upgrade
sudo apt-get dist-upgrade
</code></pre>
<p>During installation, you'll be asked to confirm changes to configuration files. I suggest pressing <code>D</code> to see differences and then following with <code>Y</code> or <code>N</code> to accept or reject changes.<br>
Especially when it comes to configuration file <code>/etc/dhcpcd.conf</code> be sure you don't loose your static IP address configuration if you had one set up.</p>
<h2 id="5cleanupafteryourself">5. Clean up after yourself</h2>
<p>Below will remove no longer needed packages and save you up some disk space. In my case it was 1GB.</p>
<pre><code class="language-bash">sudo apt-get autoremove
sudo apt-get autoclean
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Install any version of NodeJS and npm on Raspberry Pi]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Or simply put, easily switch between versions of NodeJS on any Linux based system. There are two most popular Node version managers. One, my personal favourite is <a href="https://github.com/tj/n">n package</a>, the other one is <a href="https://github.com/nvm-sh/nvm">nvm</a>.</p>
<h2 id="n">n</h2>
<p>For me the easiest way is to use <code>n</code> package. Just install whatever Node version</p>]]></description><link>https://allurcode.com/install-any-version-of-nodejs-and-npm-on-raspberry-pi/</link><guid isPermaLink="false">5b7b0aa2b52b43084c9ea14c</guid><category><![CDATA[nodejs]]></category><category><![CDATA[Raspberry Pi]]></category><category><![CDATA[npm]]></category><category><![CDATA[Linux]]></category><dc:creator><![CDATA[Wojtek]]></dc:creator><pubDate>Sat, 20 Jun 2020 17:51:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Or simply put, easily switch between versions of NodeJS on any Linux based system. There are two most popular Node version managers. One, my personal favourite is <a href="https://github.com/tj/n">n package</a>, the other one is <a href="https://github.com/nvm-sh/nvm">nvm</a>.</p>
<h2 id="n">n</h2>
<p>For me the easiest way is to use <code>n</code> package. Just install whatever Node version your official distribution ships with.</p>
<pre><code class="language-bash">sudo yum install nodejs
</code></pre>
<p>or, depending on what Linux you're using.</p>
<pre><code class="language-bash">sudo apt-get install nodejs
</code></pre>
<p>Then install <code>n</code> as a global package.</p>
<pre><code class="language-bash">sudo npm install -g n

/usr/local/bin/n -&gt; /usr/local/lib/node_modules/n/bin/n
+ n@6.5.1
added 1 package from 4 contributors in 0.201s
</code></pre>
<p>Done, it was that easy. Now install the version of node you want to use:</p>
<pre><code class="language-bash">sudo n lts &lt;--- latest LTS official release
sudo n latest &lt;--- latest official release
sudo n stable &lt;--- stable official release
sudo n 10.16.0 &lt;--- specific version
</code></pre>
<p>Execute <code>n</code> on its own to view your downloaded versions, and install the selected one.</p>
<pre><code class="language-bash">n

    node/8.11.2
    node/10.14.2
    node/10.15.0
    node/10.16.0
  ο node/12.18.1

Use up/down arrow keys to select a version, return key to install, d to delete, q to quit
</code></pre>
<h2 id="nvm">nvm</h2>
<p>Run the official <a href="https://github.com/nvm-sh/nvm/blob/v0.35.3/install.sh">install script</a> by executing one of below commands:</p>
<pre><code class="language-bash">curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash
</code></pre>
<pre><code class="language-bash">wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash
</code></pre>
<p>Rerun Profile script to start NVM</p>
<pre><code class="language-bash">source ~/.bashrc
</code></pre>
<p>Now <code>nvm</code> should be running and you can confirm it by running below</p>
<pre><code class="language-bash">nvm

Node Version Manager (v0.35.3)
</code></pre>
<p>If everything went fine, make <code>nvm</code> use your currently installed Node version</p>
<pre><code class="language-bash">nvm use system

Now using system version of node: v8.11.2 (npm v6.9.0)
</code></pre>
<p>List available versions using</p>
<pre><code class="language-bash">nvm ls-remote
</code></pre>
<p>Install the latest release of node</p>
<pre><code class="language-bash">nvm install node &lt;--- latest version
nvm install 10.16.0 &lt;--- specific version
</code></pre>
<p>If after exiting console and logging in again <code>nvm</code> is not a recognised command, you'll need to add <code>source ~/.bashrc</code> to your <code>.profile</code> or <code>.bash_profile</code> file to make sure it's automatically run on every login. A good explanation of what's going on, can be found <a href="https://apple.stackexchange.com/questions/12993/why-doesnt-bashrc-run-automatically#comment13715_13019">here</a>.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[VueJS pass data and methods to child component]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>I couldn't find a clear explanation of how to pass both data and methods from parent component to a child component in VueJS.<br>
Remember, there's always more that one way of doing almost anything. Below is just one of those ways. More detailed, albeint no so clear, explanation and all</p>]]></description><link>https://allurcode.com/vuejs-pass-data-and-methods-to-child-component/</link><guid isPermaLink="false">5e3efc2fc6c4824630385b1d</guid><category><![CDATA[vuejs]]></category><category><![CDATA[vue]]></category><category><![CDATA[component]]></category><category><![CDATA[props]]></category><dc:creator><![CDATA[Wojtek]]></dc:creator><pubDate>Sat, 08 Feb 2020 20:07:15 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>I couldn't find a clear explanation of how to pass both data and methods from parent component to a child component in VueJS.<br>
Remember, there's always more that one way of doing almost anything. Below is just one of those ways. More detailed, albeint no so clear, explanation and all the other ways of passing props can be found in <a href="https://vuejs.org/v2/guide/components-props.html">official documentation</a>.</p>
<h2 id="parentcomponent">Parent component</h2>
<p>Let's assume you have a child component called <code>Childcomponent</code>. Passing properties down to the child component is as simple as adding <code>:prop=&quot;value&quot;</code> multiple times.<br>
You can pass a single value, array <code>:ids=&quot;[324, 12, 434]&quot;</code> or an object <code>:name=&quot;{ first: 'AAA', last: 'BBB' }&quot;</code>. What was a very nice surprise for me, you can pass methods in exactly the same way. Then you can run methods from within your child component that are defined in your parent component. Super handy.</p>
<pre><code class="language-html">&lt;div id=&quot;components-demo&quot;&gt;
  &lt;Childcomponent
    :first-name=&quot;firstName&quot;
    :status=&quot;whatever.path.status&quot;
    :some-method=&quot;someMethod&quot;
    :submit=&quot;submitForm&quot; /&gt;
&lt;/div&gt;


&lt;script&gt;
import Childcomponent from '~/components/Childcomponent.vue'

export default {
  components: {
    Childcomponent
  },
  data() {
    return {
      firstName: 'whatever',
      whatever: {
        path: {
          status: true
        }
      }
    }
  },
  methods: {
    someMethod() {
      // do something
    },
    submitForm() {
      // do something else
    }
  }
}
&lt;/script&gt;
</code></pre>
<h2 id="childcomponent">Child component</h2>
<p>In child component, you need to define passed properties. Notice, in parent component prop names should use kebab case <code>first-name</code>, but when defining them in child component, use camel case <code>firstName</code>. Also methods passed from parent need to be defined in the child as a type <code>Function</code>.<br>
Then, you can use your data and methods (from parent) in the child component just as you'd do it normally.</p>
<pre><code class="language-html">&lt;template&gt;
  &lt;div&gt;
    &lt;div class=&quot;col&quot;&gt;
      &lt;img :src=&quot;loadImage(status)&quot; alt=&quot;alt text&quot;&gt;
    &lt;/div&gt;
    &lt;button
      class=&quot;btn btn-sm btn-outline-light&quot;
      @click=&quot;submit&quot;&gt;
      Submit
    &lt;/button&gt;
  &lt;/div&gt;
&lt;/template&gt;

&lt;script&gt;
export default {
  name: 'Childcomponent',
  props: {
    firstName: {
      type: String,
      default() {
        return 'My name'
      }
    },
    status: {
      type: Boolean,
      default() {
        return false
      }
    },
    loadImage: {
      type: Function,
      default() {
        return {}
      }
    },
    submit: {
      type: Function,
      default() {
        return {}
      }
    }
  }
}
&lt;/script&gt;
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Check laptop battery health on Windows 10]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>It's good practice to occasionally check the health of your laptop battery. There's a very easy way to do so on Windows 10. Of course there are lots of programs that will give you detailed information on your battery, but the built in command will also give you quite nice</p>]]></description><link>https://allurcode.com/check-laptop-battery-health-on-windows-10/</link><guid isPermaLink="false">5d6f81684a8e0f6b3f14f603</guid><category><![CDATA[Windows]]></category><category><![CDATA[battery]]></category><dc:creator><![CDATA[Wojtek]]></dc:creator><pubDate>Wed, 04 Sep 2019 10:53:55 GMT</pubDate><media:content url="https://allurcode.com/content/images/2019/09/Screenshot_24a.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://allurcode.com/content/images/2019/09/Screenshot_24a.png" alt="Check laptop battery health on Windows 10"><p>It's good practice to occasionally check the health of your laptop battery. There's a very easy way to do so on Windows 10. Of course there are lots of programs that will give you detailed information on your battery, but the built in command will also give you quite nice report.</p>
<ol>
<li>Open command line<br>
Press the Windows Key + x<br>
Choose &quot;Command Prompt&quot; or &quot;Command Prompt (Admin)&quot;<br>
<img src="https://allurcode.com/content/images/2019/09/Screenshot_23.png" alt="Check laptop battery health on Windows 10"></li>
<li>Generate the report<br>
Run below command to generate a HTML file with detailed report<pre><code>powercfg /batteryreport
</code></pre>
You should see output similar to this<pre><code>powercfg /batteryreport
Battery life report saved to file path C:\Users\your.user\current\path\battery-report.html.
</code></pre>
If you want to save the report to a specific location, add the <code>output</code> parameter as below.<pre><code>powercfg /batteryreport /output &quot;C:\custom\path\battery-report.html
</code></pre>
</li>
<li>View the report<br>
Just open your prefered browser and paste the output URL into the address bar, or find the file and double click on it to open it in the browser. You should see something similar to below screenshot.<br>
<img src="https://allurcode.com/content/images/2019/09/Screenshot_24.png" alt="Check laptop battery health on Windows 10"><br>
What you're really looking for is &quot;Installed batteries&quot; section. With a new battery the &quot;DESIGN CAPACITY&quot; and &quot;FULL CHARGE CAPACITY&quot; should be the same. The older the battery, the bigger difference between those two numbers.</li>
</ol>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Custom linting rules in NuxtJS and eslint]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p><a href="https://nuxtjs.org/">NuxtJS</a> is a fantastic framework for creating <a href="https://vuejs.org/">VueJS</a> applications. It comes bundled with Vue Router, Vuex, Vue Server Renderer and many more. All configured for you out of the box.<br>
The problem I have with it, it comes with linting options set to force 2 spaces as indentation. I'm a</p>]]></description><link>https://allurcode.com/custom-linting-rules-in-nuxtjs-and-eslint/</link><guid isPermaLink="false">5c62dae2a8a0ce0692c7bfc6</guid><category><![CDATA[nuxtjs]]></category><category><![CDATA[vuejs]]></category><category><![CDATA[eslint]]></category><category><![CDATA[chkconfig]]></category><dc:creator><![CDATA[Wojtek]]></dc:creator><pubDate>Sun, 07 Jul 2019 17:23:01 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p><a href="https://nuxtjs.org/">NuxtJS</a> is a fantastic framework for creating <a href="https://vuejs.org/">VueJS</a> applications. It comes bundled with Vue Router, Vuex, Vue Server Renderer and many more. All configured for you out of the box.<br>
The problem I have with it, it comes with linting options set to force 2 spaces as indentation. I'm a &quot;tab&quot; guy, so making me use spaces for indentation drove me crazy. It took me a while to make eslint understand I want different rules in my project. Below is a version of <code>.eslintrc.js</code> file that worked for me.</p>
<p>Obviously, I assume you've selected eslint while installing NuxtJS, so you have all the necessary modules installed. Below config has been tested with (at the time of writing this post) latest version of NuxtJS 2.8.1</p>
<pre><code class="language-javascript">module.exports = {
	root: true,
	env: {
		browser: true,
		node: true
	},
	parserOptions: {
		parser: 'babel-eslint'
	},
	extends: [
		'@nuxtjs',
		'plugin:nuxt/recommended'
	],
	// add your custom rules here
	rules: {
		'nuxt/no-cjs-in-config': 'off',
		'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
		'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
		'vue/html-indent': ['error', 'tab'],
		'vue/html-closing-bracket-newline': 'off',
		'indent': [2, 'tab'],
		'no-tabs': 'off'
	}
}
</code></pre>
<p>Go to official <a href="https://eslint.vuejs.org/rules/">eslint VueJS plugin page</a> for documentation on other rules that might suite your taste.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Prevent image hotlinking / stealing from your site with nginx]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Have you noticed other sites hotlinking to your images or other assets? Are they eating up your bandtwitch? Or you just want to proactively prevent that? If so, there's a very easy way to do so with a simple configuration on nginx.<br>
Open up nginx config file for your site</p>]]></description><link>https://allurcode.com/prevent-image-hotlinking-stealing-from-your-site-with-nginx/</link><guid isPermaLink="false">5d2217ad1e346910a0144eb4</guid><category><![CDATA[nginx]]></category><category><![CDATA[image]]></category><category><![CDATA[hotlink]]></category><dc:creator><![CDATA[Wojtek]]></dc:creator><pubDate>Sun, 07 Jul 2019 16:59:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Have you noticed other sites hotlinking to your images or other assets? Are they eating up your bandtwitch? Or you just want to proactively prevent that? If so, there's a very easy way to do so with a simple configuration on nginx.<br>
Open up nginx config file for your site and add another <code>location</code> block like this:</p>
<pre><code class="language-nginx">server {
    # your normal site configuration is here

    location ~* \.(gif|png|jpe?g)$ {
        valid_referers none blocked server_names ~\.google\. ~\.bing\. ~\.yahoo\. ~\.facebook\. ~\.yoursite.com;
        if ($invalid_referer) {
            return 403;
        }
    }
}
</code></pre>
<p>With above, we're sending <code>403 Forbidden error</code> status code whenver an image is requested from a referer that is not in our approved list.<br>
<code>valid_referers</code> lists sites which we want to allow hotlinking our images. Remember to change <code>~\.yoursite.com</code> to your actual site domain.<br>
If you want to block other file types, just add an extra pipe &quot;|&quot; and file extension, like this <code>(gif|png|jpe?g|bmp|tiff|pdf)</code></p>
<p>Going one step further, you can serve one specific image every time a not approved sites tries to hotlink to your assets. To do that add below config:</p>
<pre><code class="language-nginx">server {
    # your normal site configuration is here

    location ~* \.(gif|png|jpe?g)$ {
        valid_referers none blocked server_names ~\.google\. ~\.bing\. ~\.yahoo\. ~\.facebook\. ~\.yoursite.com;
        if ($invalid_referer) {
            rewrite (.*) /path/to/image/hotlinking-denied.jpg redirect;
        }
    }
    # prevent redirect loop
    location = /path/to/image/hotlinking-denied.jpg { }
}
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Using nginx redirect www to non-www domain]]></title><description><![CDATA[To redirect all traffic from www.example.com to just plain example.com, add another `server {}` block to your nginx config file with just two lines:
server {
    server_name www.example.com;
    return 301 $scheme://example.com$request_uri;
}]]></description><link>https://allurcode.com/using-nginx-redirect-www-to-non-www-domain/</link><guid isPermaLink="false">5d22057c1e346910a0144dee</guid><category><![CDATA[nginx]]></category><category><![CDATA[redirect]]></category><category><![CDATA[domain]]></category><dc:creator><![CDATA[Wojtek]]></dc:creator><pubDate>Sun, 07 Jul 2019 15:40:05 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Having your site configured on nginx with</p>
<pre><code class="language-nginx">server_name example.com www.example.com;
</code></pre>
<p>is a good thing as it'll allow your visitors to access your site on both <code>example.com</code> and <code>www.example.com</code>, but they'll stay on the version of the domain they used to access your site in the first place. In your analytics, you may start seeing traffic separated into <code>example.com</code> and <code>www.example.com</code> which definitely does not help you get a clear view of your visitors. It's good practice to decide on one version of the domain and stick to it. I prefer the non-www version, but it's entirely up to you.</p>
<h3 id="redirectwwwtononwww">Redirect www to non-www</h3>
<p>To redirect all traffic from <code>www.example.com</code> to just plain <code>example.com</code>, add another <code>server {}</code> block to your nginx config file with just two lines:</p>
<pre><code class="language-nginx"># new block
server {
    server_name www.example.com;
    return 301 $scheme://example.com$request_uri;
}
# your normal config
server {
    ...
    server_name example.com; # notice, this has just the non-www version
    ...
}
</code></pre>
<p>Restart nginx to apply above changes</p>
<pre><code class="language-bash">sudo systemctl restart nginx
</code></pre>
<h3 id="redirectnonwwwtowww">Redirect non-www to www</h3>
<p>To redirect your users from non-www to a www version of your domain add below:</p>
<pre><code class="language-nginx"># new block
server {
    server_name example.com;
    return 301 $scheme://www.example.com$request_uri;
}
# your normal config
server {
    ...
    server_name www.example.com;
    ...
}
</code></pre>
<p>Restart nginx to apply above changes</p>
<pre><code class="language-bash">sudo systemctl restart nginx
</code></pre>
<h3 id="conclusion">Conclusion</h3>
<p>That's it. Your users will now be able to access your site on both www and non-www versions and will be permanently redirected to one version you chose.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Configure Mailgun on self hosted Ghost blog]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p><a href="https://www.mailgun.com/">Mailgun</a> is a fantastic, <strong>free</strong> service which allows you to send, receive and track emails effortlessly. It's dead easy to integrate with your self hosted Ghost blog.</p>
<h3 id="mailgunconfiguration">Mailgun configuration</h3>
<ol>
<li>Log in to your Mailgun account.</li>
<li>Go to &quot;Domains&quot; section.</li>
<li>Click on &quot;Add New Domain&quot; and add</li></ol>]]></description><link>https://allurcode.com/configure-mailgun-on-self-hosted-ghost-blog/</link><guid isPermaLink="false">5c962968446ec0732dae7599</guid><category><![CDATA[mailgun]]></category><category><![CDATA[ghost]]></category><category><![CDATA[email]]></category><dc:creator><![CDATA[Wojtek]]></dc:creator><pubDate>Sat, 23 Mar 2019 14:36:02 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p><a href="https://www.mailgun.com/">Mailgun</a> is a fantastic, <strong>free</strong> service which allows you to send, receive and track emails effortlessly. It's dead easy to integrate with your self hosted Ghost blog.</p>
<h3 id="mailgunconfiguration">Mailgun configuration</h3>
<ol>
<li>Log in to your Mailgun account.</li>
<li>Go to &quot;Domains&quot; section.</li>
<li>Click on &quot;Add New Domain&quot; and add a subdomain you want to send emails from.</li>
<li>Follow on page instructions to add all the DNS entries.</li>
<li>Once DNS changes propagate, verify your domain within Mailgun.</li>
</ol>
<h3 id="ghostconfiguration">Ghost configuration</h3>
<ol>
<li>SSH to your server and edit <code>config.production.json</code> file in your Ghost root directory.<br>
Your &quot;mail&quot; section should look like this:<pre><code class="language-javascript">  &quot;mail&quot;: {
    &quot;transport&quot;: &quot;SMTP&quot;,
    &quot;options&quot;: {
      &quot;service&quot;: &quot;Mailgun&quot;,
      &quot;host&quot;: &quot;smtp.eu.mailgun.org&quot;,
      &quot;auth&quot;: {
        &quot;user&quot;: &quot;postmaster@your_domain.com&quot;,
        &quot;pass&quot;: &quot;1234567890&quot;
      }
    }
  }
</code></pre>
<strong>Notice</strong> <code>host</code> entry within <code>options</code>. Official Ghost documentation does not mention it. If your Mailgun domain is set up in the US region, you don't need that line. However, if you've set up your domain in the EU region, you'll need to add it in. Otherwise you'll get an error that your username and password were not recognised.</li>
<li>Save changes and restart Ghost.<pre><code class="language-bash">ghost restart
</code></pre>
</li>
<li>Log in to your Ghost admin.</li>
<li>Go to &quot;Labs&quot;.</li>
<li>Click &quot;Send&quot; in &quot;Test email configuration&quot; section.<br>
The &quot;Send&quot; button should turn green and you should receive a test email confirming your configuration works.</li>
</ol>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Update Raspbian on Raspberry Pi]]></title><description><![CDATA[Update your Raspbian by running
sudo apt-get update
then upgrade packages with
sudo apt-get dist-upgrade]]></description><link>https://allurcode.com/update-raspbian-on-raspberry-pi/</link><guid isPermaLink="false">5c798977a8a0ce0692c7bfdf</guid><category><![CDATA[Raspberry Pi]]></category><category><![CDATA[Raspbian]]></category><category><![CDATA[update]]></category><dc:creator><![CDATA[Wojtek]]></dc:creator><pubDate>Fri, 01 Mar 2019 20:09:11 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>It's highly recommended to update your Raspbian as often as possible to make sure you always have the latest security patches and updates.</p>
<h3 id="manualupdate">Manual update</h3>
<p>Open Pi's console and update package list by running the following command:</p>
<pre><code class="language-bash">sudo apt update
</code></pre>
<p>Then upgrade your packages to their latest versions with below command:</p>
<pre><code class="language-bash">sudo apt full-upgrade
</code></pre>
<p>This should keep you up to date and away from trouble.</p>
<h3 id="automaticupdates">Automatic updates</h3>
<p>If you don't like to this this manually, or simply forget about it, I suggest you set up an automatic update and never have to think about it again.<br>
There's a number of ways you can do that. There are programs that take care of that for you and have lots of options and configurations. I'll focus here on the easiest and most basic option, which is a simple cron job.<br>
Switch to root and open crontab:</p>
<pre><code class="language-bash">sudo su
crontab -e
</code></pre>
<p>If this is the first time you run crontab as root, you'll be asked to choose your preffered editor.</p>
<pre><code class="language-bash">root@raspberrypi:/home/pi# crontab -e
no crontab for root - using an empty one

Select an editor.  To change later, run 'select-editor'.
  1. /bin/ed
  2. /bin/nano
  3. /usr/bin/mcedit
  4. /usr/bin/vim.tiny  &lt;---- my favourite

Choose 1-4 [4]:
</code></pre>
<p>Once you choose your editor, enter below line at the bottom of your crontab:</p>
<pre><code class="language-bash">0 4 * * 1 apt update &amp;&amp; apt -y full-upgrade
</code></pre>
<p>Above will run update every Monday at 4am. If you prefer a different time but don't know how cron settings work, <a href="https://crontab.guru/">here's</a> a very helpful site.</p>
<!--kg-card-end: markdown--><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Create NodeJS command line script or app]]></title><description><![CDATA[Learn an extremely simple way of creating command line scripts or apps using NodeJS]]></description><link>https://allurcode.com/create-nodejs-command-line-script-or-app/</link><guid isPermaLink="false">5bc8884aa0c66e55d1ddf987</guid><category><![CDATA[nodejs]]></category><category><![CDATA[shell]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[script]]></category><dc:creator><![CDATA[Wojtek]]></dc:creator><pubDate>Sat, 15 Dec 2018 17:51:32 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>I wanted to write a simple script that would convert multiple files from one encoding to another. I didn't want anything big or running in the browser. Command line script seemed like the right approach. Coming from a web developer background my first thought was a script written in PHP and converted to a command line app. Just saying that sounds awful. After a bit of googling, it turned out NodeJS is surprisingly easy and straightforward to write command line apps.</p>
<h3 id="initiatetheapp">Initiate the app</h3>
<p>Running <code>npm init</code> will ask you a few basic questions about your app and result in creating <code>package.json</code> file.</p>
<pre><code>$ npm init

name: cldemo
version: 0.0.1
description: Simple command line script
entry point: index.js
test command:
git repository:
keywords:
author: SixBytesUnder
license: (ISC)
</code></pre>
<p>Edit the newly created <code>package.json</code> and add &quot;bin&quot; section. The property key will be the command you'll type in to run your app. In our case <code>cldemo</code>. The value is a relative path to the entry point file. That's the file our code will reside in.</p>
<pre><code class="language-javascript">...
&quot;author&quot;: &quot;SixBytesUnder&quot;,
&quot;license&quot;: &quot;ISC&quot;,
&quot;bin&quot;: {
  &quot;cldemo&quot;: &quot;./index.js&quot;
}
</code></pre>
<p>Next, create <code>index.js</code> file or any other file you have provided as an &quot;entry point&quot; above. Paste example code show below.</p>
<pre><code class="language-javascript">#!/usr/bin/env node
'use strict';

// your whole code goes here
console.log('Hello World!')
</code></pre>
<p>The most basic command line script is done.</p>
<h3 id="registeryourscript">Register your script</h3>
<p>Next command will register your app as a shell command. <strong>Note</strong>, on Windows you need to open command prompt as an admin, navigate to the home directory of your app and run below.</p>
<pre><code>$ npm install -g
</code></pre>
<p>That's it, it's a simple as that. Now you should be able to run your script from command line globally.</p>
<pre><code>$ cldemo
Hello World!
</code></pre>
<p>If you make any changes to your source files, remember to register your app again, so that latest version is copied to the global path.</p>
<p>To uninstall your script just type:</p>
<pre><code>$ npm uninstall -g cldemo
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Add reCAPTCHA to NodeJS and ExpressJS app with AJAX form]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Google's <a href="https://www.google.com/recaptcha/">reCAPTCHA</a> is great for getting rid of those pesky bots spamming your contact forms. Implementing reCAPTCHA on your site is very easy, albeit somewhat confusing if you try to follow <a href="https://developers.google.com/recaptcha/intro">official documentation</a>.<br>
Below example assumes you're using NodeJS with ExpressJS for back-end and Pug (formerly Jade) templating engine on</p>]]></description><link>https://allurcode.com/add-recaptcha-to-nodejs-and-expressjs-app-with-ajax-form/</link><guid isPermaLink="false">5ba8b26ed282fe76158958ec</guid><category><![CDATA[reCAPTCHA]]></category><category><![CDATA[nodejs]]></category><category><![CDATA[expressjs]]></category><category><![CDATA[Google]]></category><dc:creator><![CDATA[Wojtek]]></dc:creator><pubDate>Mon, 08 Oct 2018 11:01:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Google's <a href="https://www.google.com/recaptcha/">reCAPTCHA</a> is great for getting rid of those pesky bots spamming your contact forms. Implementing reCAPTCHA on your site is very easy, albeit somewhat confusing if you try to follow <a href="https://developers.google.com/recaptcha/intro">official documentation</a>.<br>
Below example assumes you're using NodeJS with ExpressJS for back-end and Pug (formerly Jade) templating engine on the front-end. General principle is the same regardless of languages used.<br>
I'll assume you've already set up your reCAPTCHA API keys. If you haven't just go to <a href="https://www.google.com/recaptcha/">https://www.google.com/recaptcha/</a> and follow onscreen instructions.</p>
<h3 id="templatefiles">Template files</h3>
<p>Open up your template file where you want to use reCAPTCHA, in my case <code>index.pug</code>. Add reference to reCAPTCHA JavaScript file as mentioned in official documentation.</p>
<pre><code class="language-pug">script(src='https://www.google.com/recaptcha/api.js')
</code></pre>
<p>Then copy the submit button code from official docs and paste it in your template, or in case of Pug, make it similar to below.</p>
<pre><code class="language-pug">button.btn.btn-default.g-recaptcha(data-sitekey=&quot;your_site_key&quot;, data-callback=&quot;contactSubmit&quot;) Submit
</code></pre>
<p>Remember to change <code>your_site_key</code> to your actual Site Key. If you're copying and pasting code from reCAPTCHA website, it should have your key already filled in.</p>
<h3 id="javascripttosubmittheform">JavaScript to submit the form</h3>
<p>Notice <code>data-callback=&quot;contactSubmit&quot;</code> in the above code for the button. Copying code for the button directly from documentation may have a different callback function name. I called mine <code>contactSubmit</code>.<br>
All you need to do is create a function in your JS file to handle form submission, making sure you pass the token value to it as an agrument and then pass it down the line to the server. Below is a pretty standard AJAX form submission example. I kept it to minimum to illustrate just the reCAPTCHA variable.</p>
<pre><code class="language-javascript">function contactSubmit(token) {
	var name = $('#contactForm #name'),
		email = $('#contactForm #email'),
		message = $('#contactForm #message');
	
	// check if the form fields are not empty
	if (name.val() !== '' &amp;&amp; email.val() !== '' &amp;&amp; message.val() !== '') {
		$.ajax({
			type: 'POST',
			url: '/handlecontact',
			data: {
				name: name.val(),
				email: email.val(),
				message: message.val(),
				recaptcha: token
			},
			dataType: 'json',
			error: function (data) {
				$('#contactForm #formFeedback')
                    .removeClass()
                    .addClass('alert alert-danger')
                    .html('Something went wrong, please try again')
                    .fadeIn('slow')
                    .delay(10000)
                    .fadeOut('slow');
				return false;
			},
			success : function (data, res) {
				if (data.success === true) {
					$('#contactForm #formFeedback')
                        .removeClass()
                        .addClass('alert alert-success')
                        .html(data.msg)
                        .fadeIn('slow')
                        .delay(5000)
                        .fadeOut('slow');
					// clean up form fields
					name.val('');
					email.val('');
					message.val('');
					return true;
				} else {
					$('#contactForm #formFeedback')
                        .removeClass()
                        .addClass('alert alert-danger')
                        .html(data.msg)
                        .fadeIn('slow')
                        .delay(10000)
                        .fadeOut('slow');
					return false;
				}
			}
		});
	} else {
		$('#contactForm #formFeedback')
            .removeClass()
            .addClass('alert alert-warning')
            .html('Please fill in all fields')
            .fadeIn('slow')
            .delay(10000)
            .fadeOut('slow');
		return false;
	}
}
</code></pre>
<h3 id="expressjsserverside">ExpressJS - server side</h3>
<p>Open ExpressJS file in which you handle your form data on the server side. In my case it's <code>index.js</code>, and add <code>https</code> module at the top to handle captcha verification request.</p>
<pre><code class="language-javascript">var https = require('https');
</code></pre>
<p>Then in the method handling your form data verify if user has passed captcha verification.<br>
All you really need to do is send the reCAPTCHA token back to Google for verification. That's what we need https module for.</p>
<pre><code class="language-javascript">app.post('/handlecontact', function (req, res) {
	// verify recaptcha
	if (req.body.recaptcha === undefined || req.body.recaptcha === '' || req.body.recaptcha === null) {
		res.send({success: false, msg: 'Please select captcha first'});
		return;
	}
	const secretKey = 'your_secret_key';
	const verificationURL = `https://www.google.com/recaptcha/api/siteverify?secret=${secretKey}&amp;response=${req.body.recaptcha}&amp;remoteip=${req.connection.remoteAddress}`;
	
	https.get(verificationURL, (resG) =&gt; {
		let rawData = '';
		resG.on('data', (chunk) =&gt; { rawData += chunk })
		resG.on('end', function() {
			try {
				var parsedData = JSON.parse(rawData);
				if (parsedData.success === true) {
					// All good, send contact email or perform other actions that required successful validation
					res.send({success: true, msg: 'Your message has been sent. Thank you.'});
					return;
				} else {
					res.send({success: false, msg: 'Failed captcha verification'});
					return;
				}
			} catch (e) {
				res.send({success: false, msg: 'Failed captcha verification from Google'});
				return;
			}
		});
	});
});
</code></pre>
<p>When testing reCAPTCHA make sure you refresh the page between &quot;submit&quot; button clicks. Otherwise Google may think you're a bot for clicking too many times and not submit the form at all.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Enable VNC (virtual desktop) on Raspberry Pi]]></title><description><![CDATA[<!--kg-card-begin: markdown--><h3 id="usingcommandline">Using command line</h3>
<p>If command line is not your cup of tea and you need graphical interface, Raspbian has just the thing for you.</p>
<ul>
<li>ssh to your Raspberry, (follow <a href="https://allurcode.com/set-up-raspberry-pi-without-a-monitor-and-keyboard-headless/">my guide here</a>, if you need to set up ssh access as well),</li>
<li>Run command<pre><code class="language-bash">sudo raspi-config
</code></pre>
</li>
<li>Select <code>Interfacing Options</code>,<br>
<img src="https://allurcode.com/content/images/2018/10/Screenshot_28.png" alt="Screenshot_28"></li>
<li>Select</li></ul>]]></description><link>https://allurcode.com/enable-vnc-on-raspberry-pi/</link><guid isPermaLink="false">5bba462b424d6d70c6ae42f8</guid><category><![CDATA[Raspberry Pi]]></category><category><![CDATA[VNC]]></category><dc:creator><![CDATA[Wojtek]]></dc:creator><pubDate>Sun, 07 Oct 2018 20:58:12 GMT</pubDate><media:content url="https://allurcode.com/content/images/2018/10/Screenshot_31-1.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><h3 id="usingcommandline">Using command line</h3>
<img src="https://allurcode.com/content/images/2018/10/Screenshot_31-1.png" alt="Enable VNC (virtual desktop) on Raspberry Pi"><p>If command line is not your cup of tea and you need graphical interface, Raspbian has just the thing for you.</p>
<ul>
<li>ssh to your Raspberry, (follow <a href="https://allurcode.com/set-up-raspberry-pi-without-a-monitor-and-keyboard-headless/">my guide here</a>, if you need to set up ssh access as well),</li>
<li>Run command<pre><code class="language-bash">sudo raspi-config
</code></pre>
</li>
<li>Select <code>Interfacing Options</code>,<br>
<img src="https://allurcode.com/content/images/2018/10/Screenshot_28.png" alt="Enable VNC (virtual desktop) on Raspberry Pi"></li>
<li>Select <code>VNC</code>,<br>
<img src="https://allurcode.com/content/images/2018/10/Screenshot_29.png" alt="Enable VNC (virtual desktop) on Raspberry Pi"></li>
<li>Select <code>Yes</code>.</li>
</ul>
<p>VNC should be active now. You can use a <a href="https://www.realvnc.com/en/connect/download/viewer/">VNC viewer</a> to connect to your RPi.</p>
<h3 id="usinggraphicaldesktop">Using graphical desktop</h3>
<p>If you have a monitor connected to your Raspberry, but would like to use it elsewhere while still having access to your RPi, you can do it in just a few steps.</p>
<ul>
<li>Go to Menu -&gt; Preferences -&gt; Raspberry Pi Configuration,</li>
<li>Click <code>Interfaces</code> tab,</li>
<li>Make sure option <code>Enabled</code> is selected for <code>VNC</code>,<br>
<img src="https://allurcode.com/content/images/2018/10/Screenshot_31.png" alt="Enable VNC (virtual desktop) on Raspberry Pi"></li>
<li>Save it by clicking <code>OK</code>.</li>
</ul>
<p>VNC should be active now. You can use a <a href="https://www.realvnc.com/en/connect/download/viewer/">VNC viewer</a> to connect to your RPi.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Set up WiFi on Raspberry Pi via command line]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Below method is useful if you don't have access to Raspbian's graphical interface. You don't need to install any additional software, everything is available out of the box and can be done in a few simple steps:</p>
<ul>
<li>ssh to your Raspberry, (follow <a href="https://allurcode.com/set-up-raspberry-pi-without-a-monitor-and-keyboard-headless/">my guide here</a>, if you need to set</li></ul>]]></description><link>https://allurcode.com/set-up-wifi-on-raspberry-pi-via-command-line/</link><guid isPermaLink="false">5bba3eb7424d6d70c6ae42f2</guid><category><![CDATA[Raspberry Pi]]></category><category><![CDATA[ssh]]></category><category><![CDATA[WiFi]]></category><dc:creator><![CDATA[Wojtek]]></dc:creator><pubDate>Sun, 07 Oct 2018 17:41:48 GMT</pubDate><media:content url="https://allurcode.com/content/images/2018/10/Screenshot_26-1.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://allurcode.com/content/images/2018/10/Screenshot_26-1.png" alt="Set up WiFi on Raspberry Pi via command line"><p>Below method is useful if you don't have access to Raspbian's graphical interface. You don't need to install any additional software, everything is available out of the box and can be done in a few simple steps:</p>
<ul>
<li>ssh to your Raspberry, (follow <a href="https://allurcode.com/set-up-raspberry-pi-without-a-monitor-and-keyboard-headless/">my guide here</a>, if you need to set up ssh access as well),</li>
<li>Run command<pre><code class="language-bash">sudo raspi-config
</code></pre>
</li>
<li>Select <code>Network Options</code> from the menu,<br>
<img src="https://allurcode.com/content/images/2018/10/Screenshot_26.png" alt="Set up WiFi on Raspberry Pi via command line"></li>
<li>Select <code>Wi-fi</code>,<br>
<img src="https://allurcode.com/content/images/2018/10/Screenshot_27.png" alt="Set up WiFi on Raspberry Pi via command line"></li>
<li>If you're asked, select your country,</li>
<li>Enter your network name (SSID),</li>
<li>Enter password</li>
</ul>
<p>That's it. You can disconnect Ethernet cable now. Remember the IP address of your RPi will most likely change from the one you had while connected via Ethernet cable.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Set up Raspberry Pi without a monitor and keyboard (headless)]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>If you don't have an extra monitor or keyboard, you can still set up your Raspberry Pi without them. SSH is not enabled by default on Raspbian, but with just a few steps we can fix that.</p>
<ul>
<li>Follow <a href="https://www.raspberrypi.org/downloads/raspbian/">official guide</a> to install Raspbian on an SD card,</li>
<li>Eject the card</li></ul>]]></description><link>https://allurcode.com/set-up-raspberry-pi-without-a-monitor-and-keyboard-headless/</link><guid isPermaLink="false">5b7b0aa2b52b43084c9ea14d</guid><category><![CDATA[Raspberry Pi]]></category><category><![CDATA[Raspbian]]></category><category><![CDATA[ssh]]></category><dc:creator><![CDATA[Wojtek]]></dc:creator><pubDate>Mon, 20 Aug 2018 18:38:26 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>If you don't have an extra monitor or keyboard, you can still set up your Raspberry Pi without them. SSH is not enabled by default on Raspbian, but with just a few steps we can fix that.</p>
<ul>
<li>Follow <a href="https://www.raspberrypi.org/downloads/raspbian/">official guide</a> to install Raspbian on an SD card,</li>
<li>Eject the card and put it back into the card reader,</li>
<li>Access boot partition on the card,</li>
<li>Create an empty file named <code>ssh</code> in the root directory of said boot partition,</li>
<li>Eject the card and insert it into your Raspberry Pi,</li>
<li>Connect Raspberry and your home router with an ethernet cable (you only need to do it once),</li>
<li>Boot up your Raspberry by plugging power in,</li>
<li>Find Raspberry's IP address. There's plenty of ways to do that. If you have access to your home router, you can see it on your device list, otherwise just <a href="https://www.google.co.uk/search?q=find+raspberry+ip+address">Google it</a>,</li>
<li>Once you know the IP address, open console. For Windows users, I highly recommend <a href="http://cmder.net/">cmder</a> and type in:<pre><code class="language-bash">ssh pi@192.168.1.99
</code></pre>
Change the <code>192.168.1.99</code> part to whatever the IP address of your RPi is.<br>
When asked for password enter: <code>raspberry</code>.</li>
<li>Done, you're in.</li>
</ul>
<p>End notes<br>
It's highly recommended to change <code>pi</code> user's password as your first action. You can do that by issuing command <code>passwd</code> while logged in as <code>pi</code> user and providing a more secure one.</p>
<p>Depending on your project, you might want to <a href="https://allurcode.com/set-up-wifi-on-raspberry-pi-via-command-line/">set up WiFi</a> to not have to keep your Raspberry cabled in to the router or <a href="https://allurcode.com/enable-vnc-on-raspberry-pi/">enable VNC server</a> to have nice graphical interface to play with.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Custom error pages in Kohana v3.x]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p><a href="http://kohanaframework.org/" title="Kohana">Kohana framework</a> displays really nice and descriptive error messages, for a development environment that is. For production, obviously no error reports should be shown to the user. Instead we should display a pretty &quot;404 Not Found&quot; page, or some other error page.<br>
Creating those custom error pages in</p>]]></description><link>https://allurcode.com/custom-error-pages-in-kohana-v3-x/</link><guid isPermaLink="false">5b7b0aa2b52b43084c9ea14b</guid><category><![CDATA[404]]></category><category><![CDATA[500]]></category><category><![CDATA[custom]]></category><category><![CDATA[error]]></category><category><![CDATA[exception]]></category><category><![CDATA[kohana]]></category><category><![CDATA[PHP]]></category><dc:creator><![CDATA[Wojtek]]></dc:creator><pubDate>Thu, 21 Feb 2013 16:13:26 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p><a href="http://kohanaframework.org/" title="Kohana">Kohana framework</a> displays really nice and descriptive error messages, for a development environment that is. For production, obviously no error reports should be shown to the user. Instead we should display a pretty &quot;404 Not Found&quot; page, or some other error page.<br>
Creating those custom error pages in Kohana v3.x can be a real pain in the bum. I’m hoping that below guide will help you get this done in just few minutes.</p>
<h2 id="createhtmlofyourcustompages">Create HTML of your custom pages</h2>
<p>Start with creating a <code>404.php</code> file here:</p>
<pre><code>/application/views/error/404.php
</code></pre>
<p>Add content you want, for example</p>
<pre><code class="language-html">&lt;h1&gt;My custom 404 error page!&lt;/h1&gt;
</code></pre>
<p>Repeat the same for a 500 error page<br>
File: <code>/application/views/error/500.php</code><br>
Code: <code>&lt;h1&gt;My custom 500 error page!&lt;/h1&gt;</code></p>
<p>Following the same pattern, you can create custom pages for all error codes. If you want one error page for all just create it and later point all requests to that view.</p>
<h3 id="createtemplateifyouneedit">Create template if you need it</h3>
<p>You can use the same template you’re using for your normal pages. If so, feel free to omit this step.</p>
<p>File: <code>/application/views/error.php</code><br>
Code: <code>&lt;?php echo $content; ?&gt;</code></p>
<h2 id="extendkohanaexceptionclass">Extend Kohana exception class</h2>
<p>Create directory and file as per below and copy code into the file.</p>
<p>File: <code>/application/classes/kohana/exception.php</code><br>
Code:</p>
<pre><code class="language-php">&lt;?php defined('SYSPATH') or die('No direct script access.');

class Kohana_Exception extends Kohana_Kohana_Exception {
  public static function handler(Exception $e) {
    if (Kohana :: $environment === Kohana :: DEVELOPMENT) {
      // In development show normal Kohana errors
      parent :: handler($e);
    } else {
      // In production show custom error page
      try {
        Kohana :: $log-&gt;add(Log :: ERROR, parent :: text($e));
        $attributes = array (
          'action' =&gt; 500,
          'message' =&gt; rawurlencode($e-&gt;getMessage())
        );
        if ($e instanceof HTTP_Exception) {
          $attributes['action'] = $e-&gt;getCode();
        }
        // Error sub-request.
        echo Request::factory(Route::get('error')-&gt;uri($attributes))-&gt;execute()-&gt;send_headers()-&gt;body();
      } catch (Exception $e) {
        // Clean the output buffer if one exists ob_get_level() and ob_clean();
        // Display the exception text
        echo parent :: text($e);
        // Exit with an error status exit (1);
      }
    }
  }
}
</code></pre>
<h2 id="addrouteforerrorpages">Add route for error pages</h2>
<p>File: <code>/application/bootstrap.php</code><br>
Code:</p>
<pre><code class="language-php">Route::set('error', 'error/&lt;action&gt;/(&lt;message&gt;)', array('action' =&gt; '[0-9]++', 'message' =&gt; '.+'))
  -&gt;defaults(array( 'controller' =&gt; 'error', 'action' =&gt; '404' ));
</code></pre>
<h2 id="finallycreatecontrollerforerrorpages">Finally, create controller for error pages</h2>
<p>File: <code>/application/controller/error.php</code></p>
<pre><code class="language-php">&lt;?php defined('SYSPATH') or die('No direct script access.');

class Controller_Error extends Controller_Template {
  // if you've created your custom error template. If not use your standard template here.
  public $template = 'error';
  public function before() {
    parent :: before();
  }
  /** * Serves HTTP 404 error page */
  public function action_404() {
    $this-&gt;template-&gt;content = View :: factory('error/404');
  }
  /** * Serves HTTP 500 error page */
  public function action_500() {
    $this-&gt;template-&gt;content = View :: factory('error/500');
  }
}
</code></pre>
<p>That’s it. Try to access a page on your site that doesn’t exist and you should see your custom 404 error page. Remember, when working in development standard Kohana errors will be shown and only on production our pretty error pages will shine. Line 6 in <code>exception.php</code> controls this behaviour.</p>
<p>Above is simplified and slightly modified version of <a href="http://blog.lysender.com/2011/02/kohana-3-1-migration-custom-error-pages/">Lysender</a> post.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item></channel></rss>