<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Kaveen's Website on Kaveen Rodrigo</title><link>https://ukr.lk/</link><description>Recent content in Kaveen's Website on Kaveen Rodrigo</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 17 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://ukr.lk/index.xml" rel="self" type="application/rss+xml"/><item><title>ESPHome on The Neo Wi-Fi Alarm</title><link>https://ukr.lk/posts/moes-neo-alarm-jailbreak/</link><pubDate>Sun, 17 May 2026 00:00:00 +0000</pubDate><guid>https://ukr.lk/posts/moes-neo-alarm-jailbreak/</guid><description>&lt;p&gt;I got handed down some Neo Wi-Fi alarms, could have set these up with Tuya app but a local setup is much better. After opening the alarm out it was clear that they use an &lt;a href="https://en.wikipedia.org/wiki/Espressif_Systems"&gt;Espressif Systems&lt;/a&gt; micro-controller.&lt;/p&gt;
&lt;p&gt;Some searches yielded that these were &lt;a href="https://tasmota.github.io/docs/"&gt;Tasmotized&lt;/a&gt; but it seemed much better to use &lt;a href="https://esphome.io/"&gt;ESPHome&lt;/a&gt; to be used with &lt;a href="https://www.home-assistant.io/"&gt;Home Assistant&lt;/a&gt;&lt;/p&gt;
&lt;details&gt;
 &lt;summary&gt;⚠️ Disclaimer&lt;/summary&gt;
 
This guide is for educational purposes only. By proceeding, you acknowledge that jailbreaking or modifying your IoT device may void its warranty, violate the manufacturer's terms of service, and potentially expose it to security vulnerabilities. This process carries the risk of permanently damaging or "bricking" your device. You assume full responsibility for any outcomes. Always ensure your actions comply with local laws and regulations.

&lt;/details&gt;

&lt;h3 id="pre-requisites"&gt;Pre-requisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;USB to TTL Convertor with 3.3v regulator (&lt;a href="https://tronic.lk/product/ch340-rs232-usb-to-ttl-converter-module-adapter?srsltid=AfmBOoo8hnVTUYU4jEkim62xFu1oNlayK10S9gx_c1-GlaxFsRIz54sV"&gt;CH340 Based&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Solid core wire (any way to make connections to the pads will do).&lt;/li&gt;
&lt;li&gt;Soldering supplies.&lt;/li&gt;
&lt;li&gt;Computer with &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Serial_API#browser_compatibility"&gt;WebSerial supported&lt;/a&gt; web browser (Tested on Google Chrome)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://esphome.io/guides/getting_started_hassio/"&gt;ESPHome&lt;/a&gt; installation.&lt;/li&gt;
&lt;li&gt;Device with Wi-Fi.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="part-1---flashing"&gt;Part 1 - Flashing&lt;/h3&gt;
&lt;p&gt;First take apart the device, being careful not to damage the flex cable, and identify the pads for the programming.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/moes-neo-alarm-jailbreak/pinout_hu_7e3f108f6669a008.webp" width="1000" height="563" class="summary-image" alt="Device pinout illustrated"&gt;
	
 &lt;figcaption&gt;Image 1: Device pinout illustrated&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p class="notice"&gt;Do not plug in the device USB cable until specified.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Solder short lengths of solid core wires to all illustrated pads.&lt;/li&gt;
&lt;li&gt;While the USB TTL convertor is unplugged wire the pads to the shown pins. (&lt;code&gt;PROG&lt;/code&gt; comes for next step)&lt;/li&gt;
&lt;li&gt;Connect the &lt;code&gt;PROG&lt;/code&gt; wire to &lt;code&gt;GND&lt;/code&gt; and plug in the USB to your computer, disconnect &lt;code&gt;PROG&lt;/code&gt; after USB is plugged in (&lt;code&gt;PROG&lt;/code&gt;/&lt;code&gt;GPIO0&lt;/code&gt; pulled down gets the micro controller to go into programming mode)&lt;/li&gt;
&lt;li&gt;Go to &lt;a href="https://web.esphome.io/"&gt;ESPHome Web Flasher&lt;/a&gt; and follow the steps to flash the initial image.&lt;/li&gt;
&lt;li&gt;Disconnect USB TTL convertor and plug in the device USB cable and power it on. You can verify if the flashing worked by checking if you see a new &lt;code&gt;esphome&lt;/code&gt; access point.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;

&lt;figure id="image-2"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/moes-neo-alarm-jailbreak/haxor_hu_8627d3b3ac7e1269.webp" width="1000" height="750" class="summary-image" alt="Success"&gt;
	
 &lt;figcaption&gt;Image 2: Success&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 id="part-2---programming"&gt;Part 2 - Programming&lt;/h3&gt;
&lt;p&gt;Now let&amp;rsquo;s provision the device and get it connect to Home Assistant.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Connect to the &lt;code&gt;esphome&lt;/code&gt; access point and get it connected to your home network.&lt;/li&gt;
&lt;li&gt;Use the &lt;a href="template.yml"&gt;template.yml&lt;/a&gt; or content given below to program the device &lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;
&lt;li&gt;Connect device to Home Assistant.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;

&lt;figure id="image-3"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/moes-neo-alarm-jailbreak/ha_hu_52b981ef484b7634.webp" width="1000" height="858" class="summary-image" alt="Profit, works as expected now"&gt;
	
 &lt;figcaption&gt;Image 3: Profit, works as expected now&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;details&gt;
 &lt;summary&gt;Expand for YAML Template&lt;/summary&gt;
 



&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;substitutions&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;neo-siren&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;friendly_name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Neo Siren&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;esphome&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;${name}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;friendly_name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;${friendly_name}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;esp8266&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;board&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;esp01_1m&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;logger&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;baud_rate&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;api&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;encryption&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;key&lt;/span&gt;: !&lt;span style="color:#ae81ff"&gt;secret api_key&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;ota&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;platform&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;esphome&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;password&lt;/span&gt;: !&lt;span style="color:#ae81ff"&gt;secret ota_password&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;wifi&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ssid&lt;/span&gt;: !&lt;span style="color:#ae81ff"&gt;secret wifi_ssid&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;password&lt;/span&gt;: !&lt;span style="color:#ae81ff"&gt;secret wifi_password&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ap&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ssid&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;${friendly_name} Fallback&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;password&lt;/span&gt;: !&lt;span style="color:#ae81ff"&gt;secret wifi_password&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;captive_portal&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;uart&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;tx_pin&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;GPIO1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;rx_pin&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;GPIO3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;baud_rate&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;9600&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;tuya&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;switch&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;platform&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;tuya&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Alarm&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;switch_datapoint&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;104&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;icon&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;mdi:alarm-bell&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;platform&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;tuya&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Temperature Alarm&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;switch_datapoint&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;113&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;icon&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;mdi:thermometer-alert&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;platform&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;tuya&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Humidity Alarm&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;switch_datapoint&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;114&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;icon&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;mdi:water-percent-alert&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;select&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;platform&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;tuya&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Alarm Sound&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;enum_datapoint&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;102&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;icon&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;mdi:music-note&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;options&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;0&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Doorbell&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;1&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Fur Elise&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;2&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Big Ben&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;3&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Ring Ring&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;4&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Lone Ranger&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;5&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Turkish March&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;6&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;High Pitch Siren&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;7&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Red Alert&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;8&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Cricket&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;9&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Beep Beep&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;10&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Dogs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;11&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Police&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;12&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Chime&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;13&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Phone Ring&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;14&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Firetruck&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;15&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Clock Chime&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;16&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Alarm Clock&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;17&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Psycho&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;number&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;platform&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;tuya&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Alarm Duration&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;number_datapoint&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;103&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;icon&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;mdi:timer&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;min_value&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;max_value&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1800&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;step&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;platform&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;tuya&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Alarm Volume&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;number_datapoint&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;116&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;icon&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;mdi:volume-high&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;min_value&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;max_value&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;step&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;sensor&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;platform&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;tuya&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Power Status&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;sensor_datapoint&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;101&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;icon&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;mdi:power-plug&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;platform&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;tuya&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Temperature&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;sensor_datapoint&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;105&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;unit_of_measurement&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;°C&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;accuracy_decimals&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;filters&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;multiply&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;0.1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;icon&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;mdi:thermometer&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;platform&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;tuya&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Humidity&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;sensor_datapoint&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;106&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;unit_of_measurement&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;%&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;accuracy_decimals&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;icon&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;mdi:water-percent&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;/details&gt;

&lt;p&gt;Got lucky with this device as it uses the well-defined non locked down chip.
If you see any old IoT devices in the market, do some research and see if they can be liberated the same way!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Edit:&lt;/strong&gt; Quite Embarrassed but there is already a template on &lt;a href="https://devices.esphome.io/devices/neo-coolcam-temperature-and-humidity-3in1-alarm-siren/"&gt;devices.esphome.io&lt;/a&gt; which for some reason I did not stumble upon while doing this. That seems to have some additional features, so do check it out.&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;Thanks to &lt;a href="https://templates.blakadder.com/neo_coolcam_NAS-AB02W.html"&gt;templates.blakadder.com&lt;/a&gt; for the Tasmota template which was used to adapt this.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Cyclone Ditwah</title><link>https://ukr.lk/posts/cyclone-ditwah/</link><pubDate>Sun, 30 Nov 2025 00:00:00 +0000</pubDate><guid>https://ukr.lk/posts/cyclone-ditwah/</guid><description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;193 deaths&lt;/strong&gt;, &lt;strong&gt;228 missing&lt;/strong&gt; and &lt;strong&gt;968,304 persons affected.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;- &lt;a href="https://www.dmc.gov.lk/images/dmcreports/Situation_Report_at_1200hrs_on_2025__1764484757.pdf"&gt;Disaster Management Center (DMC) situation report on 2025/11/30 at 12:00&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/cyclone-ditwah/jaxa_himwari_hu_28699f0e60cc1fd1.webp" width="1000" height="606" class="summary-image" alt="Sri Lanka under cyclone ditwah, captured by JAXA&amp;rsquo;s Himwari-8 satellite"&gt;
	
 &lt;figcaption&gt;Image 1: Sri Lanka under cyclone ditwah, captured by JAXA&amp;rsquo;s Himwari-8 satellite&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p class="notice"&gt;
 Please help out relief efforts any way you can. Here are some resources to do so, 
 &lt;a href="https://docs.google.com/document/d/1nurUZGpF4hTbGSBw9trINt31nQARItFxhgEiBFW3uW0/edit?usp=sharing"&gt;verified flood relief funds&lt;/a&gt; and the &lt;a href="https://www.cbsl.gov.lk/sites/default/files/cbslweb_documents/about/press_20251129_pmd_disaster_relief_fund_e.pdf?brid=tUDbLTql3Ij2DgxHqIKrsg"&gt; Government relief fund&lt;/a&gt;
&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;I want to write something, but that can wait. We are okay.&lt;/em&gt;&lt;/p&gt;</description></item><item><title>Why Do Sri Lankan Bread Three Wheelers Play Für Elise</title><link>https://ukr.lk/posts/why-do-bread-trucks-play-fur-elise/</link><pubDate>Tue, 21 Oct 2025 00:00:00 +0000</pubDate><guid>https://ukr.lk/posts/why-do-bread-trucks-play-fur-elise/</guid><description>&lt;p&gt;A constant sound track of my life, and I don&amp;rsquo;t doubt many others is &lt;a href="https://en.wikipedia.org/wiki/F%C3%BCr_Elise"&gt;Für Elise by Beethoven&lt;/a&gt;
I don&amp;rsquo;t wake up and play a worn record of Beethoven&amp;rsquo;s piano classic (maybe some do) but because of the bread three wheelers that roam every neighborhood in the morning or afternoon.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-3"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/why-do-bread-trucks-play-fur-elise/2020_c19_choonpaan_hu_555d24a137928287.webp" width="1000" height="667" class="summary-image" alt="Bread Three Wheeler / Choon Paan operating amidst COVID-19 pandemic in 2020, photo by me"&gt;
	
 &lt;figcaption&gt;Image 3: Bread Three Wheeler / Choon Paan operating amidst COVID-19 pandemic in 2020, photo by me&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;To attract the folks at home they play the tune, not a classical recording but a rudimentary monophonic synthesized rendition.
This has been the norm for long, that folks colloquially call these bread three wheelers &amp;ldquo;චූන්පාන්&amp;rdquo; not a linguist but seems like an onomatopoeia for the sound they make.&lt;/p&gt;
&lt;p&gt;But why? I keep seeing this question being asked and answered often. For me the answer has always been simple as a kid dabbling with electronics when I was small.&lt;/p&gt;
&lt;h2 id="um66t-integrated-circuit"&gt;UM66T Integrated Circuit&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s because of technology, specifically a chip called the &lt;a href="https://www.alldatasheet.com/datasheet-pdf/view/113485/UMC/UM66T.html"&gt;UM66T&lt;/a&gt;,
which is a simple melody generator chip designed to be used in telephones, door-bells, etc.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-4"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/why-do-bread-trucks-play-fur-elise/UM66T_datasheet_hu_41284ba86e23c0a9.webp" width="1000" height="714" class="summary-image" alt="Screenshot of the UM66T Datasheet"&gt;
	
 &lt;figcaption&gt;Image 4: Screenshot of the UM66T Datasheet&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;With this and a bit more components you can construct a simple circuit which can blast a single pre-programmed tune through a horn speaker,
for which we like &lt;a href="https://en.wikipedia.org/wiki/Pavlov%27s_dog_(disambiguation)"&gt;Pavlov&amp;rsquo;s dog&lt;/a&gt; conditioned to run outside to.
Check the video below to see it in action,&lt;/p&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
 &lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/w76hNJpN0pM?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
 &lt;/div&gt;

&lt;p&gt;Makes me want to grab a &lt;a href="https://www.hungrylankan.com/recipes/sri-lankan-kimbula-buns/"&gt;kimbula bunis&lt;/a&gt; and some tea.&lt;/p&gt;
&lt;p&gt;the UM66T is not a single chip but a series of chips, what we are talking about is the UM66T19L. Yes there are more.&lt;/p&gt;
&lt;h2 id="but-our-choonpaan-played-its-a-small-world"&gt;But our choonpaan played &amp;ldquo;It’s a Small World&amp;rdquo;?&lt;/h2&gt;
&lt;p&gt;Maybe your neighborhood bread three wheeler played &amp;ldquo;It’s a Small World&amp;rdquo;? Or another choonpaan rival did?
Helps this theory as &amp;ldquo;It’s a Small World&amp;rdquo; is another option of the UM66T chip series.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Given below is the complete list of part numbers and the song they played&lt;/em&gt;&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Part No.&lt;/th&gt;
 &lt;th&gt;Song Name&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;UM66T01 L/S&lt;/td&gt;
 &lt;td&gt;Jingle Bells + Santa Claus is Coming To Town + We Wish You a Merry X’mas&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;UM66T02 L/S&lt;/td&gt;
 &lt;td&gt;Jingle Bells&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;UM66T04 L/S&lt;/td&gt;
 &lt;td&gt;Jingle Bells + Rudolph, the Red-nosed Reindeer + Joy to the World&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;UM66T05 L/S&lt;/td&gt;
 &lt;td&gt;Home Sweet Home&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;UM66T06 L/S&lt;/td&gt;
 &lt;td&gt;Let Me Call You Sweetheart&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;UM66T08 L/S&lt;/td&gt;
 &lt;td&gt;Happy Birthday to You&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;UM66T09 L/S&lt;/td&gt;
 &lt;td&gt;Wedding March (Mendelssohn)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;UM66T11 L/S&lt;/td&gt;
 &lt;td&gt;Love Me Tender, Love Me True&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;UM66T13 L/S&lt;/td&gt;
 &lt;td&gt;Easter Parade&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;UM66T19 L/S&lt;/td&gt;
 &lt;td&gt;For Elise&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;UM66T32 L/S&lt;/td&gt;
 &lt;td&gt;Waltz&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;UM66T33 L/S&lt;/td&gt;
 &lt;td&gt;Mary Had a Little Lamb&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;UM66T34 L/S&lt;/td&gt;
 &lt;td&gt;The Train is Running Fast&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;UM66T68 L/S&lt;/td&gt;
 &lt;td&gt;It’s a Small World&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The more you know!&lt;/p&gt;</description></item><item><title>Note To Self: Packing for Travel</title><link>https://ukr.lk/posts/packing-for-travel/</link><pubDate>Mon, 09 Jun 2025 00:00:00 +0000</pubDate><guid>https://ukr.lk/posts/packing-for-travel/</guid><description>&lt;p&gt;I&amp;rsquo;m no packing guru, I don&amp;rsquo;t travel often and most/all of the times I do it&amp;rsquo;s for work. I went on a work trip recently. While staying in my hotel room I was thinking of my questionable packing decisions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In the lists below any unchecked item is something I missed, or opted out&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="packing-philosophy"&gt;Packing &amp;ldquo;Philosophy&amp;rdquo;&lt;/h3&gt;
&lt;p&gt;I don&amp;rsquo;t like having a lot of stuff. My goal was to pack less and take everything I need in one carry-on luggage for a week-long trip.&lt;/p&gt;
&lt;p&gt;I saw a video a year back by this YouTuber which I was reminded of (shame I didn&amp;rsquo;t re-watch it until now)&lt;/p&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
 &lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/ezSCBQPiRSo?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
 &lt;/div&gt;

&lt;p&gt;I lack style unlike Rajiv in the video, but I think the concepts do apply.&lt;/p&gt;
&lt;p class="notice"&gt;
You should just watch Rajiv's video, &lt;/br&gt; What I've put down on this post is what I missed.
&lt;/p&gt;
&lt;h3 id="toiletries"&gt;Toiletries&lt;/h3&gt;
&lt;p&gt;Essentially, whatever you use regularly you should take, I made the mistake of thinking &amp;ldquo;the shampoo in the hotel is fine&amp;rdquo;, my hair disagreed. I missed my skin care routine and it was not fun.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; Toothpaste&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; Lip balm&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; Moisturiser lotion&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; Toothbrush&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; Laundry detergent&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; Cologne&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Shampoo&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Face Wash&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="clothes"&gt;Clothes&lt;/h3&gt;
&lt;p&gt;I don&amp;rsquo;t own much clothes, and my nonexistent styling means I pair my jeans (I have exactly two of the same) with some t-shirts.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; Cotton Tees&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; Comfy shorts x1&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; Jeans x2&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; Fancy Shirt x1 (Doubles as layer)&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Outdoor shorts x1&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Blazer&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Fancy pants&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Fancy shoes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;m often prepared to wash my clothes at the hotel, for which I do take some laundry detergent. But I was a bit worried this time If I&amp;rsquo;d be able to dry them off.&lt;/p&gt;
&lt;p&gt;I used to pack a suite (at least use blazer with jeans on the plane) that I do miss.&lt;/p&gt;
&lt;h3 id="accessories"&gt;Accessories&lt;/h3&gt;
&lt;h4 id="shoes"&gt;Shoes&lt;/h4&gt;
&lt;p&gt;I took some Adidias Stan Smith&amp;rsquo;s, they are not comfortable for long walks, I wish I packed something else. With the omission of a suite I did leave my fancy shoes as well.&lt;/p&gt;
&lt;h4 id="miscellaneous"&gt;Miscellaneous&lt;/h4&gt;
&lt;p&gt;Random nice to haves. I missed my flip flops.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Comfy flip flops&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Tote bag&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Small water bottle&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="packing-for-weather"&gt;Packing for weather&lt;/h4&gt;
&lt;p&gt;I messed this up, got a bit sick as it&amp;rsquo;s cold. I packed just a denim t-shirt (not thick) this was not enough. I need to get a jacket next time.&lt;/p&gt;
&lt;h3 id="luggage"&gt;Luggage&lt;/h3&gt;
&lt;p&gt;This is important, I only took carry on luggage this time, I should have taken a foldable bag for random shopping hauls.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; Backpack
&lt;ul&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; Toiletries bag&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; Carry on luggage&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Foldable bag&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Checked in luggage&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="conclusion"&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;In summary, think a bit more before packing!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I made the write decision not to wash and dry clothes, if it&amp;rsquo;s for leisure that will work but not for business.&lt;/li&gt;
&lt;li&gt;Make sure you pack for the weather.&lt;/li&gt;
&lt;li&gt;Versatile parings.&lt;/li&gt;
&lt;li&gt;I only took one carry on luggage, Should have taken a just in case bag which I could used to pack gifts and a lot of coffee beans.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/packing-for-travel/flowers_in_ams_hu_305ea95ed1adbdf6.webp" width="1000" height="1328" class="summary-image" alt="Flowers in Amsterdam"&gt;
	
 &lt;figcaption&gt;Image 1: Flowers in Amsterdam&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;</description></item><item><title>Making a custom Google Sheets function for currency conversion</title><link>https://ukr.lk/posts/combank-exchange-rates-in-google-sheets/</link><pubDate>Sun, 26 Jan 2025 00:00:00 +0000</pubDate><guid>https://ukr.lk/posts/combank-exchange-rates-in-google-sheets/</guid><description>&lt;p&gt;I use google sheets for my personal finance work and require buying rates for foreign currencies.
At first I just had a constant set, then used the Google Finance function but that value is way off.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-2"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/combank-exchange-rates-in-google-sheets/combuying_hu_c800433409b01574.webp" width="1000" height="563" class="summary-image" alt="Post thumbnail showing the function in use"&gt;
	
 &lt;figcaption&gt;Image 2: Post thumbnail showing the function in use&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 id="making-our-own-function"&gt;Making our own function&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://developers.google.com/apps-script"&gt;Google Apps Script&lt;/a&gt; is what we need to make this work.
Using Apps Script it&amp;rsquo;s easy to write a custom function for Google Sheets.&lt;/p&gt;
&lt;h4 id="task-1-data-source"&gt;Task 1: Data Source&lt;/h4&gt;
&lt;p&gt;This was easy, After browsing the official websites &lt;a href="https://www.combank.lk/tools-calculators#exchange-rates-calculator"&gt;currency convert page&lt;/a&gt;, I saw this API call heading out&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://www.combank.lk/api/exchange-rates/"&gt;https://www.combank.lk/api/exchange-rates/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;and the schema was simple and clear, this is all we need to make this happen.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;excode&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;USD&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;description&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;US DOLLARS&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;code&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;cheque_buying_rate&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;291.89164&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;cheque_selling_rate&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;302.5&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;currency_buying_rate&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;292.9534&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;currency_selling_rate&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;302.5&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;telegraphic_transfers_buying_rate&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;294.5&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;telegraphic_transfers_selling_rate&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;302.5&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;sync_at&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;2025-01-24&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;created_at&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;2020-12-16 11:37:31&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;updated_at&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;2025-01-26 08:30:03&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="task-2-writing-the-function"&gt;Task 2: Writing the function&lt;/h4&gt;
&lt;p&gt;To make a custom function on Google sheets, Do the following,&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go/Make to the Google Sheet.&lt;/li&gt;
&lt;li&gt;In the menu bar click &lt;em&gt;Extensions&lt;/em&gt; then &lt;em&gt;App Script&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Write the code in the given &lt;code&gt;code.gs&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;Click the Save icon on the tool bar.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Afterwards the function is available on the Sheet.&lt;/p&gt;
&lt;p&gt;The code was mostly generated using an LLM, it was functional. That was easy!
I added some tweaks to make it a bit nicer (caching, docs, etc.)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * Get the latest currency buying value for Commercial Bank
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * @param {currencyCode} ISO currency code
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * @return converted value
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; * @customfunction
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;COMBUYING&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;currencyCode&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;cacheKey&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;exchangeRates&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;apiUrl&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;https://www.combank.lk/api/exchange-rates/&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;cache&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;CacheService&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getScriptCache&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;exchangeRates&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {};
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;try&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Check if data is already cached
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;cache&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;get&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;cacheKey&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Fetch the API response if not cached
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;response&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;UrlFetchApp&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;fetch&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;apiUrl&lt;/span&gt;, { &lt;span style="color:#a6e22e"&gt;method&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;get&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;muteHttpExceptions&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;response&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getContentText&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Cache the data for 10 minutes
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;cache&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;put&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;cacheKey&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;600&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;exchangeRates&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;JSON&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;parse&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;catch&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;e&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;throw&lt;/span&gt; Error(&lt;span style="color:#e6db74"&gt;`Unable to fetch exhcange rates &lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;e&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Find the currency by its code
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;currency&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;exchangeRates&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;find&lt;/span&gt;((&lt;span style="color:#a6e22e"&gt;item&lt;/span&gt;) =&amp;gt; &lt;span style="color:#a6e22e"&gt;item&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;excode&lt;/span&gt; &lt;span style="color:#f92672"&gt;===&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;currencyCode&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;toUpperCase&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;currency&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;throw&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;SyntaxError&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;`Currency &amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;currencyCode&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34; not found`&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;currency&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;currency_buying_rate&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="task-3-use-it"&gt;Task 3: Use it!&lt;/h4&gt;
&lt;p&gt;Now with the function name, we&amp;rsquo;re able to fetch the latest buying rate for any currency.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;COMBUYING&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;EUR&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="conclusion"&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Thanks to a prior run in with Google App Script, I knew of this possibility.
ChatGPT is great for these kind of quick hacks to get something started.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s convenient as the rates given by Google Finance and actual buying rates differ. Comparison of outputs on the day of writing,&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Function&lt;/th&gt;
 &lt;th&gt;Result&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;GOOGLEFINANCE(&amp;quot;CURRENCY:EURLKR&amp;quot;)&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;312.75&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;COMBUYING(&amp;quot;EUR&amp;quot;)&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;303.56077&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;</description></item><item><title>Look back at 2024</title><link>https://ukr.lk/posts/look-back-on-2024/</link><pubDate>Wed, 01 Jan 2025 00:00:00 +0000</pubDate><guid>https://ukr.lk/posts/look-back-on-2024/</guid><description>&lt;p&gt;Happy New Year Everyone! I wish all of y&amp;rsquo;all a happy and healthy new year.&lt;/p&gt;
&lt;p&gt;I Typed my first words of this post with a very downer note, but upon reflecting the year past my mood was lifted. It got me excited for what to come!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Here&amp;rsquo;s the best of 2024, in chronological order.&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="ran-my-first-5k-marathon"&gt;Ran my first 5K Marathon&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;February, 2024 - &lt;a href="https://en.wikipedia.org/wiki/Colombo_Racecourse"&gt;Race Course Colombo 7&lt;/a&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;It has been a good couple of years since I started training for a run with the &lt;a href="https://www.nhs.uk/live-well/exercise/get-running-with-couch-to-5k/"&gt;Couch to 5K&lt;/a&gt; program,
It was not easy with restarting the program multiple times in the span of years, but I trusted the system and trained through.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/look-back-on-2024/runfortheirlives_hu_b507dfb6096bb9bc.webp" width="1000" height="750" class="summary-image" alt="Run For Their Lives 2024, At Race Course Colombo"&gt;
	
 &lt;figcaption&gt;Image 1: Run For Their Lives 2024, At Race Course Colombo&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Was excited to take part in this charity run, was doubtful if I&amp;rsquo;d complete but the atmosphere and energy at &lt;a href="http://www.rftl.lk/"&gt;Run For Their Lives&lt;/a&gt; was amazing. I was able to complete 5KM in 33 minutes which I was happy about.&lt;/p&gt;
&lt;h3 id="bought-a-house"&gt;Bought a house&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;April, 2024 - &lt;a href="https://en.wikipedia.org/wiki/Battaramulla"&gt;Battaramulla&lt;/a&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I Always wanted a place of my own but wasn&amp;rsquo;t actively searching. Was fortunate to be offered a deal that was too-good to let go.
It was a house built in the 90&amp;rsquo;s but needed some attention as it was left abandoned for a couple of years.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-2"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/look-back-on-2024/house_hu_7c09d002a571b17.webp" width="1000" height="750" class="summary-image" alt="Interior of abandoned house, it needed a lot of TLC"&gt;
	
 &lt;figcaption&gt;Image 2: Interior of abandoned house, it needed a lot of TLC&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;I was able to work out a mortgage with my bank. My naïveté assumed that&amp;rsquo;s all to be done. I was in for a ride with this one.&lt;/p&gt;
&lt;h3 id="got-married"&gt;Got Married&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;May, 2024 - &lt;a href="https://web.archive.org/web/20240903153151/http://www.stmarysbambalapitiya.org/"&gt;St. Mary&amp;rsquo;s Church&lt;/a&gt; &lt;a href="https://en.wikipedia.org/wiki/Bambalapitiya"&gt;Bambalapitiya&lt;/a&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;We got married, It was a beautiful day which started a new chapter in our lives, where it&amp;rsquo;s no longer &lt;em&gt;&amp;ldquo;I&amp;rdquo;&lt;/em&gt; but &lt;em&gt;&amp;ldquo;We&amp;rdquo;&lt;/em&gt;.
My wife moved to &lt;a href="https://en.wikipedia.org/wiki/Colombo"&gt;Colombo&lt;/a&gt; from her hometown &lt;a href="https://en.wikipedia.org/wiki/Kandy"&gt;Kandy&lt;/a&gt; which was not easy, but I&amp;rsquo;m so grateful.
I&amp;rsquo;m so happy and lucky to have her by my side.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-3"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/look-back-on-2024/wedding_hu_c8d8b8209054a694.webp" width="1000" height="750" class="summary-image" alt="Wedding ceremony at St. Mary&amp;rsquo;s Church - Bambalapitiya"&gt;
	
 &lt;figcaption&gt;Image 3: Wedding ceremony at St. Mary&amp;rsquo;s Church - Bambalapitiya&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;As for the ceremony&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt; itself, there was a lot of planning involved throughout 2023 leading to the day, but it was great to celebrate among family and friends.&lt;/p&gt;
&lt;h3 id="renovating"&gt;Renovating&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;July, 2024 (Ongoing) - &lt;a href="https://en.wikipedia.org/wiki/Battaramulla"&gt;Battaramulla&lt;/a&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;We are still renovating the house, good news is that we will be able to move in a couple of weeks.
It was a long, often frustrating process. But it will all be justified once we move in and make this house a home.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-4"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/look-back-on-2024/renovations_hu_e05795c2cdd267af.webp" width="1000" height="752" class="summary-image" alt="House renovations"&gt;
	
 &lt;figcaption&gt;Image 4: House renovations&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;The last couple of months were packed with swatches, checking vendors and a lot of &lt;em&gt;&amp;ldquo;Hmmm, what do you think?&amp;rdquo;&lt;/em&gt;.
But we&amp;rsquo;re excited to move in!&lt;/p&gt;
&lt;p&gt;There was a lot of learnings doing this, I shall write a bit more about it later.&lt;/p&gt;
&lt;h3 id="axi"&gt;Axi&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;August, 2024 - &lt;a href="https://en.wikipedia.org/wiki/Sri_Jayawardenepura_Kotte"&gt;Sri Jayawardenepura Kotte&lt;/a&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I was driving back home from friends one rainy night, and a kitten appeared in-front of my car and got knocked by the bumper.
The cat distribution system has struck again.&lt;/p&gt;
&lt;p&gt;Took her to the vet, and she was okay, it was apparent that she has always been a bit clumsy.
Not so graceful jumping from high trees like our cat &lt;em&gt;&amp;ldquo;Ashey&amp;rdquo;&lt;/em&gt; who was not amused by the new guest.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-5"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/look-back-on-2024/axi_hu_cfffcdd2e05eee5d.webp" width="1000" height="750" class="summary-image" alt="Axi shenanigans"&gt;
	
 &lt;figcaption&gt;Image 5: Axi shenanigans&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;I took her back home (living with my parents until the house is complete) and everyone loves her. Dad named the cat &lt;em&gt;&amp;ldquo;Axi&amp;rdquo;&lt;/em&gt; short for &lt;em&gt;&amp;ldquo;Accident&amp;rdquo;&lt;/em&gt; which I found amusing.
Axi has been a constant source of cute chaos around the house, which made the year very memorable.&lt;/p&gt;
&lt;h3 id="looking-forward"&gt;Looking Forward&lt;/h3&gt;
&lt;p&gt;There are a couple of things I was critical about, which I intend to justify in this new year.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Get healthy, again&lt;/strong&gt; - I fell off the wagon again, gained back most of my weight. I do know where I went wrong.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Be a better husband&lt;/strong&gt; - I want to be a better partner. Doing my best and learning!&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Better manage my finances with the new circumstances&lt;/strong&gt; - New responsibilities, my simple finance playbook won&amp;rsquo;t fly.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Read and write more&lt;/strong&gt; - My past time has become binging copious amount of YouTube, I need to better use my time.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Edits/Updates&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;(2025/01/02)&lt;/strong&gt; My wife reminded me that I forgot to talk about the cat, Axi was a highlight in the year, so added a section.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;It was actually two ceremonies, we had one at the church and a traditional Sri Lankan &lt;a href="https://en.wikipedia.org/wiki/Poruwa_ceremony"&gt;poruwa ceremony&lt;/a&gt; in June.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Unsubscribing All Dialog Promotional Texts</title><link>https://ukr.lk/posts/blocking-all-marketing-sms-dialog/</link><pubDate>Wed, 13 Nov 2024 07:50:02 +0530</pubDate><guid>https://ukr.lk/posts/blocking-all-marketing-sms-dialog/</guid><description>&lt;p class="notice"&gt;
 This post is only valid for customers of Dialog in Sri Lanka.
&lt;/p&gt;
&lt;p&gt;Everyone dislikes spam texts&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;, Sri Lanka has an issue with data-brokers and data protection issues, as it was recently evident by the &lt;a href="https://www.themorning.lk/articles/ot1STkNVg01wDHOS2TsA"&gt;influx of unwarranted political messages for the general election 2024&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I digress&lt;/strong&gt;. But there is a simple solution to knock out a bunch of these messages if you are a Dialog consumer. It was much more simpler than expected.&lt;/p&gt;
&lt;p&gt;Most are aware of how to unsubscribe via &lt;code&gt;9010&lt;/code&gt; with &lt;code&gt;BL &amp;lt;APP NAME&amp;gt;&lt;/code&gt; which allows you to block an company/provider.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;One day with some dumb luck I sent a &lt;code&gt;BL All&lt;/code&gt; to &lt;code&gt;9010&lt;/code&gt; and realized that you&amp;rsquo;re able to lock out all promotional texts.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/blocking-all-marketing-sms-dialog/messages_hu_90b4a7b6832ab589.webp" width="1000" height="938" class="summary-image" alt="Android Messages App Showing Subscription"&gt;
	
 &lt;figcaption&gt;Image 1: Android Messages App Showing Subscription&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;That was an easy win, granted this does not mean you&amp;rsquo;ll be spam free. But this will ensure any party using Dialog&amp;rsquo;s promotional message system will not reach you.&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;SMS Messages&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Personal Finance: Cashflow, Budgets &amp; Projections</title><link>https://ukr.lk/posts/personal-finances-1/</link><pubDate>Mon, 19 Aug 2024 18:57:29 +0530</pubDate><guid>https://ukr.lk/posts/personal-finances-1/</guid><description>&lt;p&gt;Some notes on how to get a grasp of your finances and make sure you&amp;rsquo;re able to achieve what you set out.&lt;/p&gt;
&lt;h3 id="preface--disclaimer"&gt;Preface &amp;amp; Disclaimer&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;I&amp;rsquo;m not a financial advisor. All numbers put forward in this document is for illustrative purposes only.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Managing your finances is hard. I&amp;rsquo;m not here to give advice or guidance on managing cash, but give some notes on how I manage mine. Do note I&amp;rsquo;m in Sri Lanka, so the context of financial products and process will defer with your background and jurisdiction. But the core points are still valid.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;For me personal finance and financial literacy starts with knowing how your money is being used, this is what we are going to explore in this note.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3 id="step-0-what-do-you-want"&gt;Step 0: What do you want?&lt;/h3&gt;
&lt;p&gt;What are your goals, these are justified in doing this exercise. Mine currently are,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Making sure that my finances are used to achieve my goals (currently it&amp;rsquo;s renovating the home we bought), and ensure that I&amp;rsquo;m investing and saving up to do so.&lt;/li&gt;
&lt;li&gt;Being able to carry on in absence of primary income for 5 months. Ie- pay loans, living expenses, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="step-1-where-am-i-now"&gt;Step 1: Where am I now?&lt;/h3&gt;
&lt;p&gt;First it&amp;rsquo;s important to understand how you&amp;rsquo;re current predicament. To do this the following needs to be categorized first.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Incomes&lt;/strong&gt; (Inflows)
&lt;ul&gt;
&lt;li&gt;Salaried Income&lt;/li&gt;
&lt;li&gt;Interest Income&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Assets&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Fixed Assets&lt;/strong&gt; (Long term tangible assets)
&lt;ul&gt;
&lt;li&gt;House&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Liquid Assets&lt;/strong&gt; (Highly accessible/cashable assets)
&lt;ul&gt;
&lt;li&gt;Savings Account&lt;/li&gt;
&lt;li&gt;Current Account&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Non-Current Assets&lt;/strong&gt; (Investments with maturity dates over one year)
&lt;ul&gt;
&lt;li&gt;Investment Plan&lt;/li&gt;
&lt;li&gt;Term Deposits&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Expenses&lt;/strong&gt; (Outflows)
&lt;ul&gt;
&lt;li&gt;Joint Expenses&lt;/li&gt;
&lt;li&gt;Personal Expenses&lt;/li&gt;
&lt;li&gt;Mortgage repayments&lt;/li&gt;
&lt;li&gt;Investment plan payment&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Next step is to figure out how your cash in/out flow works out with these assets. What you need is the following,&lt;/p&gt;
&lt;p&gt;Illustrated below is my personal current overall cash flow and how it propagates.&lt;/p&gt;

&lt;figure id="illustration-3"&gt;
 &lt;pre class="mermaid"&gt;flowchart LR
 I1([Income]) --&gt;|Monthly| S(Savings)
 S --&gt;|Monthly| J(Joint Current Account)
 %%I1P([Income Partner]) --&gt;|Monthly| J
 J --&gt; JE([Join Expenses])
 S --&gt;|Monthly| M(Mortgage)
 S --&gt;|Monthly| C([Credit Card])
 C --&gt; PE([Personal Expenses])
 S --&gt;|Monthly| I(Investment Plan)
 &lt;/pre&gt;
 &lt;figcaption&gt;Illustration 3&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;It&amp;rsquo;s much more complicated than shown here as sometimes there are hidden links, for example how I&amp;rsquo;d use my Credit Card for Joint expenses, which I keep track and reconcile.&lt;/p&gt;
&lt;h3 id="step-2-cashflowbudget-statement"&gt;Step 2: Cashflow/Budget Statement&lt;/h3&gt;
&lt;p&gt;Now it&amp;rsquo;s time to make a cashflow/budget statement, with the data you collected you&amp;rsquo;re able to make a spreadsheet that put&amp;rsquo;s all into one place.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Category and Subcategory&lt;/th&gt;
 &lt;th style="text-align: right"&gt;Amount (LKR)&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Inflows&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: right"&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&amp;gt; Salary income&lt;/td&gt;
 &lt;td style="text-align: right"&gt;500,000&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&amp;gt; Interest income&lt;/td&gt;
 &lt;td style="text-align: right"&gt;20,000&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Total Inflows&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: right"&gt;&lt;strong&gt;520,000&lt;/strong&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Outflows&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: right"&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&amp;gt; Joint expenses&lt;/td&gt;
 &lt;td style="text-align: right"&gt;150,000&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&amp;gt; Mortgage&lt;/td&gt;
 &lt;td style="text-align: right"&gt;120,000&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&amp;gt; Investment&lt;/td&gt;
 &lt;td style="text-align: right"&gt;100,000&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&amp;gt; Credit card bill&lt;/td&gt;
 &lt;td style="text-align: right"&gt;80,000&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Total Outflows&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: right"&gt;&lt;strong&gt;450,000&lt;/strong&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Net Cash Flow&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: right"&gt;&lt;strong&gt;70,000&lt;/strong&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="sidebar-budgeting"&gt;Sidebar: Budgeting&lt;/h3&gt;
&lt;p&gt;You&amp;rsquo;re budget depends on your circumstance and the risks you&amp;rsquo;re able to take based on that circumstance. But for most of us a good starting point is to take a look at the &lt;a href="https://en.wikipedia.org/w/index.php?title=Personal_budget#50/30/20_budget"&gt;50/30/20 Rule&lt;/a&gt;&lt;/p&gt;

&lt;figure id="illustration-4"&gt;
 &lt;pre class="mermaid"&gt;graph LR
 A([Total Income]) --&gt; B[50% Needs]
 A --&gt; C[30% Wants]
 A --&gt; D[20% Savings]

 B --&gt; B1[Housing]
 B --&gt; B2[Utilities]
 B --&gt; B3[Groceries]
 B --&gt; B4[Insurance]

 C --&gt; C1[Dining Out]
 C --&gt; C2[Entertainment]
 C --&gt; C3[Shopping]

 D --&gt; D1[Emergency Fund]
 D --&gt; D2[Retirement Savings]
 D --&gt; D3[Investments]
 &lt;/pre&gt;
 &lt;figcaption&gt;Illustration 4&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The illustration above shows how outflows can be categorized. With that lets see how our example inflows should be utilized.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Category&lt;/th&gt;
 &lt;th&gt;Percentage&lt;/th&gt;
 &lt;th style="text-align: right"&gt;Amount (LKR)&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Needs&lt;/td&gt;
 &lt;td&gt;50%&lt;/td&gt;
 &lt;td style="text-align: right"&gt;260,000&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Wants&lt;/td&gt;
 &lt;td&gt;30%&lt;/td&gt;
 &lt;td style="text-align: right"&gt;156,000&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Savings&lt;/td&gt;
 &lt;td&gt;20%&lt;/td&gt;
 &lt;td style="text-align: right"&gt;104,000&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;100%&lt;/td&gt;
 &lt;td style="text-align: right"&gt;&lt;strong&gt;520,000&lt;/strong&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="step-3-basic-projections"&gt;Step 3: Basic projections&lt;/h3&gt;
&lt;p&gt;Now that you&amp;rsquo;re aware of your inflows and outflows, projections are required to see of how best to achieve your goals in the long run. For now, I&amp;rsquo;m going to talk about some basic projections based on the net cashflow for now.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Description&lt;/th&gt;
 &lt;th&gt;2024&lt;/th&gt;
 &lt;th&gt;2025&lt;/th&gt;
 &lt;th&gt;2026&lt;/th&gt;
 &lt;th&gt;2027&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Net Cashflow&lt;/td&gt;
 &lt;td&gt;70,000&lt;/td&gt;
 &lt;td&gt;70,000&lt;/td&gt;
 &lt;td&gt;70,000&lt;/td&gt;
 &lt;td&gt;70,000&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Savings&lt;/td&gt;
 &lt;td&gt;840,000&lt;/td&gt;
 &lt;td&gt;1,680,000&lt;/td&gt;
 &lt;td&gt;2,520,000&lt;/td&gt;
 &lt;td&gt;3,360,000&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Projections are way more complex than this example.
A more powerful form of this would be to have all your assets with their indexation and interest, so you&amp;rsquo;re able to see you&amp;rsquo;re assets grow. Perhaps that&amp;rsquo;s diving in too deep for now.&lt;/p&gt;
&lt;h3 id="conclusion"&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;These are notes, a dump of basic ideas to get started on planning your wealth. I started ths post of with a lot of ambition, but condensing all down to a single post in no easy task.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m planning to make some easy tools to put these into action, hopefully I&amp;rsquo;ll hack something out when time permits!&lt;/p&gt;</description></item><item><title>Bulk correct skewed timestamps on photos using exiftool</title><link>https://ukr.lk/posts/shift-dates-using-exiftool/</link><pubDate>Fri, 05 Jul 2024 21:30:23 +0530</pubDate><guid>https://ukr.lk/posts/shift-dates-using-exiftool/</guid><description>&lt;p&gt;I got my wedding pictures, a folder with a set of JPEG&amp;rsquo;s taken from a bunch of cameras. I was happy, but annoyingly when looking at the photos chronologically as it&amp;rsquo;s clear some have wrong timestamps causing the order to be out of whack.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/shift-dates-using-exiftool/gr-gunning_hu_c8ff5803e6b6d106.webp" width="1000" height="752" class="summary-image" alt="Random photo running around with the Ricoh GR in Kandy"&gt;
	
 &lt;figcaption&gt;Image 1: Random photo running around with the Ricoh GR in Kandy&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s fix it up with &lt;a href="https://exiftool.org"&gt;exiftool&lt;/a&gt;! On macOS, you can easily get it installed using brew.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brew install exiftool
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="figuring-out-what-went-wrong"&gt;Figuring out what went wrong&lt;/h3&gt;
&lt;p&gt;I knew instinctively that it must be a wrong time setting on a camera. I do it myself at times, when the camera boots up, and you quickly punch in a date and a time.&lt;/p&gt;
&lt;p&gt;I first need to take stock of all the images, specifically the&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;File name&lt;/li&gt;
&lt;li&gt;Serial number (unique camera identifier)&lt;/li&gt;
&lt;li&gt;Taken timestamp&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;exiftool -T -FileName -SerialNumber -DateTimeOriginal -ext jpg .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then after manually relating a couple of photos, I found the culprit! One camera which had a time-delta of 11 hours, yikes!&lt;/p&gt;
&lt;h3 id="offsetting-the-timestamp"&gt;Offsetting the timestamp&lt;/h3&gt;
&lt;p&gt;Now that I know the serial number of the camera and the required to be offset to fix the discrepancy, we can use exiftool to fix it.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;exiftool -if &lt;span style="color:#e6db74"&gt;&amp;#39;$SerialNumber eq &amp;#34;7601644&amp;#34;&amp;#39;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;-AllDates+=11:54:09&amp;#34;&lt;/span&gt; -ext jpg .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Using the &lt;code&gt;-if&lt;/code&gt; switch I&amp;rsquo;m able to filter out one serial number. You can get rid of this if you can apply to all images.&lt;/p&gt;
&lt;h3 id="removing-the-original-backups"&gt;Removing the original backups&lt;/h3&gt;
&lt;p&gt;You would have noticed that there are original files left by exiftool, which can be used to revert any blunders. You can remove the original backups using the following command.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;exiftool -delete_original .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>About my wife</title><link>https://ukr.lk/posts/about-my-wife/</link><pubDate>Mon, 17 Jun 2024 21:44:38 +0530</pubDate><guid>https://ukr.lk/posts/about-my-wife/</guid><description>&lt;p&gt;You bring out feelings that I thought I never had, the look of love I saw in others&amp;rsquo; eyes before that I assumed wasn&amp;rsquo;t in me. I can only assume the strong feeling of nurture that I feel looking into your eyes would feel alien to the person I was. But now it&amp;rsquo;s all second nature.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/about-my-wife/aru_hu_4f4a1892053d11fa.webp" width="1000" height="748" class="summary-image" alt="everything, 2023"&gt;
	
 &lt;figcaption&gt;Image 1: everything, 2023&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m writing this as we&amp;rsquo;re apart temporarily. The longing I feel being away from you awaits the belonging I feel in your reach.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Until our next call, with love, Kaveen.&lt;/em&gt;&lt;/p&gt;</description></item><item><title>Coffee in Kandy</title><link>https://ukr.lk/posts/coffee-in-kandy/</link><pubDate>Sun, 09 Jun 2024 12:30:57 +0530</pubDate><guid>https://ukr.lk/posts/coffee-in-kandy/</guid><description>&lt;p&gt;Sometimes there isn&amp;rsquo;t much to do in Kandy, but today I just wanted a cup of coffee. I felt a tad lonesome staying at my in-laws with my partner away at work.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;There is something charming about Kandy,&amp;rdquo; is what I planned to write once I got to this coffee place I stumbled upon on Google Maps.&lt;/p&gt;
&lt;p&gt;I took a Kandy PickMe to get to this establishment, and it was rough. He was one of those drivers who doesn&amp;rsquo;t know how to check Maps. I felt bad and held back for a good 15 minutes until he rolled into my in-laws&amp;rsquo; place. Getting there was no cakewalk either. I said to go in the general direction of the &amp;ldquo;maligawa&amp;rdquo; (Temple of the Tooth), but being a non-native in Kandy, I also took a wrong turn. Long story short, I had to walk another block to get to the coffee shop.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;The location is &lt;a href="https://maps.app.goo.gl/8QACvMFTiexVu9jH9"&gt;Department Of Coffee, Colombo Street, Kandy&lt;/a&gt;, Yes, they are affiliated with the one in Colombo.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;But now I&amp;rsquo;m delighted, seated after placing an order for a single-origin V60 brew. This better be good.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/coffee-in-kandy/v60_hu_d8bed5d3a5bcab76.webp" width="1000" height="753" class="summary-image" alt="Coffee at last, nice presentation and atmosphere as well"&gt;
	
 &lt;figcaption&gt;Image 1: Coffee at last, nice presentation and atmosphere as well&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;The coffee is good. I&amp;rsquo;m glad; it would have made my situation extra crummy otherwise.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t have the experience, palate, or vocabulary to review coffee. But it&amp;rsquo;s not burnt, which is what you get at most places. It has the right amount of acidity and hits the spot. I&amp;rsquo;d like to hang back and sample some of the food, but I&amp;rsquo;m running late as I intend to pick up my partner from her place of work. Maybe another 15-20 minutes. Paid up and had a look at the food options—they look promising. Will return again!&lt;/p&gt;
&lt;p&gt;I apologize for the rambling. If y&amp;rsquo;all are craving some specialty coffee in Kandy, this might be the place for you!&lt;/p&gt;</description></item><item><title>Customizing Wedding Cards With Python</title><link>https://ukr.lk/posts/wedding-cards-py/</link><pubDate>Sun, 19 May 2024 16:45:49 +0530</pubDate><guid>https://ukr.lk/posts/wedding-cards-py/</guid><description>&lt;p&gt;Our wedding is coming up, and I&amp;rsquo;m running out of time. It&amp;rsquo;s a bit hectic, trying to plan two events in two different places hundred kilometers apart.&lt;/p&gt;
&lt;p&gt;I was planning to give my friends invites but was running out of time fast, Had to send the invites digitally; via WhatsApp to be precise.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/wedding-cards-py/cards_tuk_hu_ab9a4b03e4e8257e.webp" width="1000" height="732" class="summary-image" alt="Physical cards, hot off the printers a week back"&gt;
	
 &lt;figcaption&gt;Image 1: Physical cards, hot off the printers a week back&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;I can&amp;rsquo;t just send an blank invite, that&amp;rsquo;s too impersonal! Have to at least address it to the invitee.&lt;/p&gt;
&lt;h3 id="automating-it"&gt;Automating it!&lt;/h3&gt;
&lt;p&gt;As you can see my card is fairly simple, just need to tack on some text in the middle and it works.
I decided to ask &lt;a href="https://en.wikipedia.org/wiki/ChatGPT"&gt;ChatGPT&lt;/a&gt; to make me a script for that. With the following requirements,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Take an input text file with a guest name in each new line&lt;/li&gt;
&lt;li&gt;Open a PNG of my wedding card&lt;/li&gt;
&lt;li&gt;Iterate and add horizontally centered name with a predefined vertical offset&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It failed at it, It misunderstood my need at first (probably my fault) but most importantly it wasn&amp;rsquo;t aware of deprecated API&amp;rsquo;s of &lt;a href="https://pypi.org/project/pillow/"&gt;Pillow&lt;/a&gt; (the library of choice for image processing in Python)&lt;/p&gt;
&lt;p&gt;After hacking on the script for a couple of minutes, I was able to get it to working.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;from&lt;/span&gt; PIL &lt;span style="color:#f92672"&gt;import&lt;/span&gt; Image, ImageDraw, ImageFont
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;FONT_SIZE &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;60&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;FONT_TTF &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;DancingScript-Regular.ttf&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;add_names_to_invitation&lt;/span&gt;(suffix, invitation_path, y_offset, names_file_path, output_folder):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Open the wedding invitation image&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; invitation_image &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Image&lt;span style="color:#f92672"&gt;.&lt;/span&gt;open(invitation_path)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Define coordinates for the center alignment&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; width, height &lt;span style="color:#f92672"&gt;=&lt;/span&gt; invitation_image&lt;span style="color:#f92672"&gt;.&lt;/span&gt;size
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; center_x &lt;span style="color:#f92672"&gt;=&lt;/span&gt; width &lt;span style="color:#f92672"&gt;//&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Load a font for the names&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; font &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ImageFont&lt;span style="color:#f92672"&gt;.&lt;/span&gt;truetype(FONT_TTF, FONT_SIZE)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Open the file containing names&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;with&lt;/span&gt; open(names_file_path, &lt;span style="color:#e6db74"&gt;&amp;#39;r&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; file:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; idx, name &lt;span style="color:#f92672"&gt;in&lt;/span&gt; enumerate(file):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Remove newline characters&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name &lt;span style="color:#f92672"&gt;=&lt;/span&gt; name&lt;span style="color:#f92672"&gt;.&lt;/span&gt;strip()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Make copy of the image&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cur &lt;span style="color:#f92672"&gt;=&lt;/span&gt; invitation_image&lt;span style="color:#f92672"&gt;.&lt;/span&gt;copy()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; draw &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ImageDraw&lt;span style="color:#f92672"&gt;.&lt;/span&gt;Draw(cur)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Calculate position for each name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; text_width &lt;span style="color:#f92672"&gt;=&lt;/span&gt; draw&lt;span style="color:#f92672"&gt;.&lt;/span&gt;textlength(name, font&lt;span style="color:#f92672"&gt;=&lt;/span&gt;font)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name_x &lt;span style="color:#f92672"&gt;=&lt;/span&gt; center_x &lt;span style="color:#f92672"&gt;-&lt;/span&gt; text_width &lt;span style="color:#f92672"&gt;//&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name_y &lt;span style="color:#f92672"&gt;=&lt;/span&gt; y_offset &lt;span style="color:#f92672"&gt;-&lt;/span&gt; FONT_SIZE &lt;span style="color:#f92672"&gt;//&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Add the name to the invitation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; draw&lt;span style="color:#f92672"&gt;.&lt;/span&gt;text((name_x, name_y), name, fill&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;black&amp;#34;&lt;/span&gt;, font&lt;span style="color:#f92672"&gt;=&lt;/span&gt;font)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Save the invitation with the name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; output_path &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;output_folder&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/invitation_&lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;name&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;_&lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;suffix&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;.png&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cur&lt;span style="color:#f92672"&gt;.&lt;/span&gt;save(output_path)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(&lt;span style="color:#e6db74"&gt;f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Writing &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;output_path&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; __name__ &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; names_file_path &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;guest_names.txt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; output_folder &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;output&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; add_names_to_invitation(&lt;span style="color:#e6db74"&gt;&amp;#34;cmb&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;Colombo Card.png&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1160&lt;/span&gt;, names_file_path, output_folder)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; add_names_to_invitation(&lt;span style="color:#e6db74"&gt;&amp;#34;kdy&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;Kandy Card.png&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1095&lt;/span&gt;, names_file_path, output_folder)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I threw in a &lt;a href="https://www.1001freefonts.com/dancing-script.font"&gt;custom script font&lt;/a&gt; which is attributed&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt; as public domain. I had two different cards, for which I just made the method functional with parameters for the y axis offset and a file name suffix.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-2"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/wedding-cards-py/output_folder_hu_bdd956fbbf9ddf28.webp" width="1000" height="574" class="summary-image" alt="The output folder with all the named cards!"&gt;
	
 &lt;figcaption&gt;Image 2: The output folder with all the named cards!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 id="why-not-do-it-manually"&gt;Why not do it manually?&lt;/h3&gt;
&lt;p&gt;I get so frustrated at times doing things manually, especially in the realm of computing as the task of the computer is to reduce repetition, so I wouldn&amp;rsquo;t have. Also two cards per person, would have made it a fun task&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;But thanks to LLM giving me a good enough starting point, was able to get it done in a short amount of time, &lt;strong&gt;the code is yucky, but it serves it&amp;rsquo;s purpose.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-3"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/wedding-cards-py/automation_hu_d32fe7f5ae5e0357.webp" width="1000" height="1010" class="summary-image" alt="Appropriate XKCD"&gt;
	
 &lt;figcaption&gt;Image 3: Appropriate &lt;a href="https://xkcd.com/1319/"&gt;XKCD&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;It didn&amp;rsquo;t turn out to be like the Automation XKCD, which I&amp;rsquo;m happy about. My fiancée also made use of it to send some digital cards.&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;Font Licensing is tricky I hear&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;For the two events, I made two cards, in retrospect should have made a third alternative with both event detail&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Birthday reflections and news!</title><link>https://ukr.lk/posts/happy-birthday-2024/</link><pubDate>Sun, 12 May 2024 09:12:03 +0530</pubDate><guid>https://ukr.lk/posts/happy-birthday-2024/</guid><description>&lt;p&gt;Another year around the sun, or what ever the folks call it these days. This has been one of those birthday&amp;rsquo;s (it was yesterday) that didn&amp;rsquo;t feel hollow like they used to feel. I&amp;rsquo;m reminded of the people who I love and cherished by.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/happy-birthday-2024/birhday_spread_hu_3ad156dbf108a5e3.webp" width="1000" height="1328" class="summary-image" alt="Birthday spread, prepared by my mother for the temple"&gt;
	
 &lt;figcaption&gt;Image 1: Birthday spread, prepared by my mother for the temple&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;This month has been hectic with what&amp;rsquo;s in store for me. I met this amazing girl a year back and we decided to get married(end of this month!) With that we bought a house&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;. A lot of folks said that it may not be wise to &lt;del&gt;buy&lt;/del&gt; mortgage that amidst all else; I do agree but we got a deal that cannot be ignored.&lt;/p&gt;
&lt;p&gt;I digress, this was not the year I join the prestigous&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt; club with Kurt Cobain, Jimi Hendrix, Jim Morrison, etc (grim, I know) as a much naiver me would have joked about. Key term &lt;em&gt;joke&lt;/em&gt; is important; was never serious about that, I should have been in retrospect.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;self realization moment: what a horrible thing to say.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I woke up today, with a clean head and am excited for the future! cheers!&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;Real piece of work, requires a lot of elbow greese.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/27_Club"&gt;27 Club&lt;/a&gt; a statistical anomoly? Culteral phenomena nevertherless.&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Migrating my blog, again (Hugo)</title><link>https://ukr.lk/posts/hugo-blog-migration/</link><pubDate>Sun, 28 Apr 2024 16:19:34 +0530</pubDate><guid>https://ukr.lk/posts/hugo-blog-migration/</guid><description>&lt;p&gt;Time goes by fast, the last time I posted on this site was in 2022. I&amp;rsquo;m alive and doing well, more than well to be honest, a lot of good news&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;But today let&amp;rsquo;s talk about the state of this website. In the last week there has been a considerable change to the makeup and hosting of this website. It wen&amp;rsquo;t from being a Next.js website hosted on Netlify to being a Hugo SSG(static site generator) on a Debian VPS on Linode. This site has always been an SSG, even with Next.JS it was using the static html export feature.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/hugo-blog-migration/thumbnail_hu_d9683430a3f02d84.webp" width="1000" height="750" class="summary-image" alt="Negambo, Sri Lanka, 2024"&gt;
	
 &lt;figcaption&gt;Image 1: Negambo, Sri Lanka, 2024&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 id="why-am-i-doing-this"&gt;Why am I doing this?&lt;/h2&gt;
&lt;p&gt;Before getting into specifics, looking back there has been a lot of changes in the way I approach these problems. I must accept my naiveté and short sighted when setting my website four years back.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m looking for simplicity and having control of my website in this new implementation.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I&amp;rsquo;m tired of keeping the dependencies up to date of a JavaScript project&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;
&lt;li&gt;The website was one of my first Next.JS projects therefore it has some questionable code and questionable DX.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="migrating-to-hugo"&gt;Migrating to Hugo&lt;/h2&gt;
&lt;p&gt;Hugo is a static site generator written in Go, I&amp;rsquo;ve never been interested in learning Go have always been aware of all the tools that I used daily that are written and maintained with it. Also a year back I took up a new job which uses Go as the primary backend language, but I digress.&lt;/p&gt;
&lt;p&gt;There is no customisation here, I downloaded a copy of Hugo and chucked in my content and bootstrapped a custom theme using &lt;a href="http://simplecss.org"&gt;simple.css&lt;/a&gt;&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;I was able to hit the ground running fairly quickly by dropping my markdown files with YAML frontmatter.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;title&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;RSS Feed for next.js blog&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;description&lt;/span&gt;: &amp;gt;-&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; On creating an RSS feed for this blog, and how it&amp;#39;s not as tedious as you think.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;date&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;2021-06-19T17:12:26.723Z&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;thumbnail&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;cmb_np.jpg&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;category&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;projects&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;web-dev&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;tags&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;nextjs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;type&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;post&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;slug&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;rss_feed_nextjs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Configuring multiple taxonomies based on the attributes was straightforward.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[&lt;span style="color:#a6e22e"&gt;taxonomies&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;category&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#39;category&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;tag&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#39;tags&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But one of my biggest pain points was asset management, before there was a singular folder which had all of my images and it was a mess. I wanted to switch over to use &lt;a href="https://gohugo.io/content-management/page-resources/"&gt;page resources&lt;/a&gt; instead, which will have all the assets needed on the content folder itself.&lt;/p&gt;
&lt;p&gt;With my laziness, coaxing chat-gpt and spending more time bug fixing resulted in this script, which migrated all my blog posts to their own folders with relative links to images.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; os
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; shutil
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; re
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;migrate_markdown&lt;/span&gt;(source_dir, destination_dir, base_img_path):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Ensure destination directory exists&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;not&lt;/span&gt; os&lt;span style="color:#f92672"&gt;.&lt;/span&gt;path&lt;span style="color:#f92672"&gt;.&lt;/span&gt;exists(destination_dir):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; os&lt;span style="color:#f92672"&gt;.&lt;/span&gt;makedirs(destination_dir)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Iterate through Markdown files in source directory&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; filename &lt;span style="color:#f92672"&gt;in&lt;/span&gt; os&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listdir(source_dir):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; filename&lt;span style="color:#f92672"&gt;.&lt;/span&gt;endswith(&lt;span style="color:#e6db74"&gt;&amp;#34;.md&amp;#34;&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Read Markdown file&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;with&lt;/span&gt; open(os&lt;span style="color:#f92672"&gt;.&lt;/span&gt;path&lt;span style="color:#f92672"&gt;.&lt;/span&gt;join(source_dir, filename), &lt;span style="color:#e6db74"&gt;&amp;#34;r&amp;#34;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; file:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; markdown_content &lt;span style="color:#f92672"&gt;=&lt;/span&gt; file&lt;span style="color:#f92672"&gt;.&lt;/span&gt;read()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Extract folder name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; folder_name &lt;span style="color:#f92672"&gt;=&lt;/span&gt; os&lt;span style="color:#f92672"&gt;.&lt;/span&gt;path&lt;span style="color:#f92672"&gt;.&lt;/span&gt;splitext(filename)[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Create folder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; new_folder_path &lt;span style="color:#f92672"&gt;=&lt;/span&gt; os&lt;span style="color:#f92672"&gt;.&lt;/span&gt;path&lt;span style="color:#f92672"&gt;.&lt;/span&gt;join(destination_dir, folder_name)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; os&lt;span style="color:#f92672"&gt;.&lt;/span&gt;makedirs(new_folder_path)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Move Markdown file&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; new_markdown_path &lt;span style="color:#f92672"&gt;=&lt;/span&gt; os&lt;span style="color:#f92672"&gt;.&lt;/span&gt;path&lt;span style="color:#f92672"&gt;.&lt;/span&gt;join(new_folder_path, &lt;span style="color:#e6db74"&gt;&amp;#34;index.md&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; shutil&lt;span style="color:#f92672"&gt;.&lt;/span&gt;copy(os&lt;span style="color:#f92672"&gt;.&lt;/span&gt;path&lt;span style="color:#f92672"&gt;.&lt;/span&gt;join(source_dir, filename), new_markdown_path)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Copy images to folder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; img_paths &lt;span style="color:#f92672"&gt;=&lt;/span&gt; re&lt;span style="color:#f92672"&gt;.&lt;/span&gt;findall(&lt;span style="color:#e6db74"&gt;r&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;/img/([\w-]+.\w{1,5})&amp;#34;&lt;/span&gt;, markdown_content)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; img_path &lt;span style="color:#f92672"&gt;in&lt;/span&gt; img_paths:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; img_filename &lt;span style="color:#f92672"&gt;=&lt;/span&gt; os&lt;span style="color:#f92672"&gt;.&lt;/span&gt;path&lt;span style="color:#f92672"&gt;.&lt;/span&gt;basename(img_path)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; shutil&lt;span style="color:#f92672"&gt;.&lt;/span&gt;copy(os&lt;span style="color:#f92672"&gt;.&lt;/span&gt;path&lt;span style="color:#f92672"&gt;.&lt;/span&gt;join(base_img_path, img_path), os&lt;span style="color:#f92672"&gt;.&lt;/span&gt;path&lt;span style="color:#f92672"&gt;.&lt;/span&gt;join(new_folder_path, img_filename))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Update image paths to be relative&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; markdown_content &lt;span style="color:#f92672"&gt;=&lt;/span&gt; re&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sub(&lt;span style="color:#e6db74"&gt;r&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;/img/([^&amp;#39;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;\(\)]+)&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;r&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;\1&amp;#34;&lt;/span&gt;, markdown_content)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Write updated Markdown content&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;with&lt;/span&gt; open(new_markdown_path, &lt;span style="color:#e6db74"&gt;&amp;#34;w&amp;#34;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; new_file:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; new_file&lt;span style="color:#f92672"&gt;.&lt;/span&gt;write(markdown_content)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Example usage&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;source_dir &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;./posts&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;destination_dir &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;./content/posts&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;base_img_path &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;./static/img&amp;#34;&lt;/span&gt; &lt;span style="color:#75715e"&gt;# Base path for images&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;migrate_markdown(source_dir, destination_dir, base_img_path)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="tips-i-wish-id-knew-days-back"&gt;Tips I wish I&amp;rsquo;d knew days back&lt;/h2&gt;
&lt;p&gt;Yes to RTFM, but these are the customisations that were done.&lt;/p&gt;
&lt;h3 id="customize-markdown-image-rendering"&gt;Customize markdown image rendering&lt;/h3&gt;
&lt;p&gt;It&amp;rsquo;s best that the image tags in markdown be rendered in a &lt;code&gt;figure&lt;/code&gt; tag and have compression applied you can do that using an hook in the layouts directory. &lt;code&gt;layouts/_default/_markup/render-image.html&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{{- $imgURL := .Destination -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{{- $altText := .Text -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{{ $image := .Page.Resources.Get $imgURL }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;figure&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{{ if $image }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		{{ $image = $image.Process &amp;#34;resize 1000x webp q50&amp;#34; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&amp;lt;&lt;span style="color:#f92672"&gt;img&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{{ $image.RelPermalink }}&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;summary-image&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{{ end }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;figcaption&lt;/span&gt;&amp;gt;{{ $altText }}&amp;lt;/&lt;span style="color:#f92672"&gt;figcaption&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;figure&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This also has image processing, where I requested that the images be resized to 1000px on width and exported as &lt;code&gt;webp&lt;/code&gt; with 50% quality.&lt;/p&gt;
&lt;h3 id="minifying-css"&gt;Minifying CSS&lt;/h3&gt;
&lt;p&gt;I found the documentation on this, but what I missed was the fact that the css files should be in the &lt;code&gt;assets&lt;/code&gt; directory not the &lt;code&gt;static&lt;/code&gt; directory.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{{ $style := resources.Get &amp;#34;style.css&amp;#34; | minify | fingerprint }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{{ $custom := resources.Get &amp;#34;custom.css&amp;#34; | minify | fingerprint }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;link&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;rel&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;stylesheet&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{{ $style.Permalink }}&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;link&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;rel&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;stylesheet&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{{ $custom.Permalink }}&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="minifying-html-content"&gt;Minifying HTML content&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;d guessed this is done via configuration, but it&amp;rsquo;s done using during the build stage using a cli flag&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;hugo --minify
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Migrating to hugo only took me a couple of days, and compared to the custom Next.js code base, this is much better DX and updating my toolchain is only a single step to replace the hugo binary. This is one of the reasons not choosing to opt into using Tailwind as well.&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;Shall post about that soon&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;Did use dependbot, but then proceeded to forget about it&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;Do enjoyed my old website theme made with Tailwind, but wanted to get started quickly. Might re-visit it later&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Euclidean Groove Thing</title><link>https://ukr.lk/posts/euclidean-groove-thing/</link><pubDate>Thu, 22 Dec 2022 18:40:04 +0530</pubDate><guid>https://ukr.lk/posts/euclidean-groove-thing/</guid><description>&lt;p&gt;Exploration into Euclidean Distribution and Its Musical Properties.&lt;/p&gt;
&lt;p&gt;I built a four-part sequencer that uses Euclidean distribution to trigger sounds and notes.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/euclidean-groove-thing/screenshot_hu_c2e32e7de3cb18d6.webp" width="1000" height="698" class="summary-image" alt="Screenshot of the app"&gt;
	
 &lt;figcaption&gt;Image 1: Screenshot of the app&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You can play around with it online, &lt;a href="https://euclideangroove.projects.ukr.lk"&gt;euclideangroove.projects.ukr.lk&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As for the melody, the notes are picked using a &amp;ldquo;Turing machine,&amp;rdquo; a modular staple that uses shift registers and probability to generate musical notes&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;In concept, I accomplished what I set out to do. However, the web-appification of it is not the best. The randomly generated tunes are, at best, chaotic. I shall revisit this project one day.&lt;/p&gt;
&lt;p&gt;Built using:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://p5js.org"&gt;p5.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tonejs.github.io"&gt;Tone.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/bitcraftlab/p5.gui"&gt;p5.gui.js&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;Gross simplification, check this video for more information &lt;a href="https://www.youtube.com/watch?v=va2XAdFtmeU&amp;amp;t=2s"&gt;https://www.youtube.com/watch?v=va2XAdFtmeU&amp;amp;t=2s&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Song of Life</title><link>https://ukr.lk/posts/song-of-life/</link><pubDate>Thu, 24 Nov 2022 19:01:47 +0530</pubDate><guid>https://ukr.lk/posts/song-of-life/</guid><description>&lt;p&gt;Song of Life is a piece of software I wrote to explore an idea I had: &amp;ldquo;What would Conway&amp;rsquo;s Game of Life sound like?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;At the time, I was experimenting with p5.js and wrote a simple Game of Life playfield. I turned this world into a sequencer, where the y-axis represents time, and the x-axis represents the musical scale.&lt;/p&gt;
&lt;p&gt;After growing tired of just a single major scale, I decided to introduce some randomness and transform it into a web app.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/song-of-life/screenshot_hu_7245563cec9f8300.webp" width="1000" height="756" class="summary-image" alt="Screenshot of the app"&gt;
	
 &lt;figcaption&gt;Image 1: Screenshot of the app&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You can play around with it online, &lt;a href="https://songoflife.projects.ukr.lk"&gt;songoflife.projects.ukr.lk&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Using a random number as a seed, the web app generates a unique world on load and associates it with a unique scale and key.&lt;/p&gt;
&lt;p&gt;What I found more fascinating than the formation phase is the stabilization of the world, which sometimes yields a pleasing melody.&lt;/p&gt;</description></item><item><title>Accountability Is What We Need</title><link>https://ukr.lk/posts/2022-situation-accountability/</link><pubDate>Wed, 06 Apr 2022 06:19:24 +0530</pubDate><guid>https://ukr.lk/posts/2022-situation-accountability/</guid><description>&lt;p&gt;A couple of weeks back I wrote some words &lt;a href="https://ukr.lk/posts/2022-situation-responsbility-sri-lanka"&gt;&amp;ldquo;What&amp;rsquo;s good with leaders who don&amp;rsquo;t take responsibility?&amp;rdquo;&lt;/a&gt;. Present-day, the state is feeling the power of the people. They are on the streets influencing and requesting what they deserve, a better Sri Lanka.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;people have spoken out their anger with many colourful slogans, but will that distract from what we need?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/2022-situation-accountability/protest_hu_3c145b701ed50cc8.webp" width="1000" height="625" class="summary-image" alt="protest in the neighbourhood"&gt;
	
 &lt;figcaption&gt;Image 1: protest in the neighbourhood&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 id="what-do-we-need"&gt;What Do We Need?&lt;/h2&gt;
&lt;p&gt;Accountability. I&amp;rsquo;m not an expert in law or politics to pinpoint what exactly is wrong. &lt;strong&gt;But I and many do know the fact how people of power in this country get away with many a crime, they&amp;rsquo;ve built up the perfect system for it.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We need accountability for,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;War Crimes&lt;/li&gt;
&lt;li&gt;Human Rights Violations&lt;/li&gt;
&lt;li&gt;Misuse Of Public Funds&lt;/li&gt;
&lt;li&gt;Crimes Against Journalists&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="to-all-those-on-the-good-fight"&gt;To All Those On The Good Fight&lt;/h2&gt;
&lt;p&gt;Calling them, colourful slogans and catchy protest songs are all good. &lt;em&gt;Not so good is that if they get away with it.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;So make sure that your message is clear! Don&amp;rsquo;t just ask them to go home, make homophobic remarks, etc.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ask them to be impeached and held accountable&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>What's good with leaders who don't take responsibility?</title><link>https://ukr.lk/posts/2022-situation-responsbility-sri-lanka/</link><pubDate>Sun, 20 Mar 2022 19:40:10 +0530</pubDate><guid>https://ukr.lk/posts/2022-situation-responsbility-sri-lanka/</guid><description>&lt;p&gt;It&amp;rsquo;s been a hard couple of years for the people of Sri Lanka, I&amp;rsquo;ve been one of the Lucy ones privileged and had a great environment to not be affected by what&amp;rsquo;s going on in this county. Which is now crumbling down, everyone is starting to feel the pressure.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/2022-situation-responsbility-sri-lanka/just_a_broom_hu_8a58b1af3a303d31.webp" width="1000" height="677" class="summary-image" alt="Just a broom"&gt;
	
 &lt;figcaption&gt;Image 1: Just a broom&lt;/figcaption&gt;
&lt;/figure&gt;

The people of Sri Lankan have been scorn and have been broken and endured by many situations, some to note,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Easter Attacks.&lt;/li&gt;
&lt;li&gt;COVID-19 Deaths.&lt;/li&gt;
&lt;li&gt;A Crumbling Economy.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A couple of days back, we&amp;rsquo;re seeing the effects of the weakening of the economy. Everyone is starting to feel the heat, devaluation of currency inflating prices of essential goods. Rolling power cuts hampering the working class, etc.&lt;/p&gt;
&lt;p&gt;People of this country are on the streets waiting in line for basic resources to keep themselves and their families fed.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Up to today(March 20, 2022) two senior citizens have lost their lives waiting in line to get essential resources.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I was taught one thing as a child, &lt;strong&gt;always apologize and internalize to be better if you did or cause something to go wrong. As a leader, especially.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;What hurt me the most was the leaders of this country who do not take accountability and brush things off very nonchalantly.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;You can&amp;rsquo;t blame the people, the very laws and regulations that were set in place and the enviroment built up by the same leaders are to blame. &lt;strong&gt;What&amp;rsquo;s good with leaders who don&amp;rsquo;t take responsibility?&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Look Back At 2021</title><link>https://ukr.lk/posts/twenty_twenty_one_retro/</link><pubDate>Sun, 02 Jan 2022 05:31:50 +0000</pubDate><guid>https://ukr.lk/posts/twenty_twenty_one_retro/</guid><description>&lt;p&gt;It&amp;rsquo;s another year. As many others, I felt indifferent this new year and Christmas in general. Even in the last months of 2021 double takes done on the calendar to realize that it&amp;rsquo;s not 2020. It was an extension of the year since the pandemic took its toll on earth.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/twenty_twenty_one_retro/2021retro_hu_47f5e3cf478fe26c.webp" width="1000" height="750" class="summary-image" alt="Home"&gt;
	
 &lt;figcaption&gt;Image 1: Home&lt;/figcaption&gt;
&lt;/figure&gt;

Many died, some made good money and the others suffered in hunger. Another year with odds stacked unfavorably to the needy and vulnerable. Meanwhile, I was in autopilot, getting into the groove of balancing perfection and getting things done. Going to sleep in the hopes of a good breakfast and pacing though the day, caffeinated, looking for a hot shower in the eve.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s not as somber as it sounds. As I wasn&amp;rsquo;t alone, many others followed the same. Tweeting hot takes, chattering on calls and vented about the trials that tied them alone with thoughts. Some forgot the pandemic, many cried about it, and the others accepted the status quo.&lt;/p&gt;
&lt;p&gt;I woke up to “Here Comes The Sun” every day, but a many decided not to step out of the house to see it in person. But its presence filtered though the curtains and on to the floor, So I did not fret. When the days of meeting friend did come, I dressed in my favorite clothes and doused my self with cologne, and it was fun.&lt;/p&gt;</description></item><item><title>COVID-19 Vax Locations</title><link>https://ukr.lk/posts/project_notes_vax_center_finder/</link><pubDate>Wed, 13 Oct 2021 16:10:15 +0000</pubDate><guid>https://ukr.lk/posts/project_notes_vax_center_finder/</guid><description>&lt;p&gt;This story is reaching this blog two months late, at present moment I&amp;rsquo;m unable to summarize the status quo when starting this project.&lt;/p&gt;
&lt;p&gt;Apart from just building a website with data, &lt;strong&gt;I&amp;rsquo;d like y&amp;rsquo;all to takeaway the importance of open data availability&lt;/strong&gt;. Which a couple of the projects I&amp;rsquo;ve been tackling have been running into trouble with.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/project_notes_vax_center_finder/vax_site_header_hu_bd13f684c6d6bf3d.webp" width="1000" height="563" class="summary-image" alt="From a simple PDF to a site"&gt;
	
 &lt;figcaption&gt;Image 1: From a simple PDF to a site&lt;/figcaption&gt;
&lt;/figure&gt;

Enough preamble, let&amp;rsquo;s get into the genesis, development and aftermath of this project.&lt;/p&gt;
&lt;h2 id="inspiration"&gt;Inspiration&lt;/h2&gt;
&lt;p&gt;My parents we&amp;rsquo;re lucky to be vaccinated quite early on, but a lot of folks were having a hard time finding vaccination centers. The present system was that the centers we&amp;rsquo;re decided daily; and published on the &lt;a href="https://www.presidentsoffice.gov.lk/index.php/vaccination-dashboard/"&gt;Presidential Secretariat website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I was quite disappointed to see that this data was offered as a PDF file. It was clumsy and only offered in English. I got know that this was a shared sentiment across different folks.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;img src="https://ukr.lk/posts/project_notes_vax_center_finder/vax_site_data_src.png"&gt;
&lt;/figure&gt;

During the daily doom scroll rounds of Twitter I came across &lt;a href="https://www.nuwan.org"&gt;Nuwan I. Senaratna&lt;/a&gt;&amp;rsquo;s tweet. He had spun up a GitHub repository and auto-scraped the data to TSV (a machine readable format) daily.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://twitter.com/nuuuwan/status/1427214177622450180"&gt;Tweet Link&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This was the enabler for this project, and I&amp;rsquo;d like to thank Nuwan on his contributions for building open datasets!&lt;/p&gt;
&lt;h2 id="requirement"&gt;Requirement&lt;/h2&gt;
&lt;p&gt;With the data-set available, I was ready to get on the development. I wrote down a couple of basic requirements that I want to fulfill with the web-app.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Trilingual Internationalization. Support Sinhala, Tamil and English.&lt;/li&gt;
&lt;li&gt;Find vaccination centers by city.&lt;/li&gt;
&lt;li&gt;Show geo-location details and links for Google Maps.&lt;/li&gt;
&lt;li&gt;Responsive / Mobile First.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Simple, the non-functional ones being,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Easy To Deploy.&lt;/li&gt;
&lt;li&gt;Easy To Develop. (by myself)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I added some nice to have enhancements down the line as well. Also some &lt;a href="https://github.com/kaveenr/lk-c19-vaccination-site-listing/graphs/contributors"&gt;other folk&lt;/a&gt; did help me out as well.&lt;/p&gt;
&lt;h2 id="development"&gt;Development&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m not a good frontend web developer, It&amp;rsquo;s not my day-job. I&amp;rsquo;ve worked with early React, but I have not caught up with developments in the space. But I always do keep my ears up on Twitter to see what&amp;rsquo;s &amp;ldquo;hot&amp;rdquo;. I knew I want to use the following.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://nextjs.org"&gt;Next JS&lt;/a&gt; (Was already comfortable, as this blog was built on Next)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://tailwindcss.com"&gt;Tailwind CSS&lt;/a&gt; (Newcomer, but what a pleasant surprise)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://mapbox.com"&gt;Mapbox&lt;/a&gt; (Just works?)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I started out with the Tailwind &amp;amp; Next JS template and I was ready!&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npx create-next-app -e with-tailwindcss lk-covid19-open-dash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;NextJS&amp;rsquo;s &lt;a href="https://nextjs.org/docs/advanced-features/i18n-routing"&gt;Internationalization routing&lt;/a&gt; coupled with &lt;a href="https://github.com/amannn/next-intl"&gt;next-intl&lt;/a&gt; was easy to use. And internationalization was easy. Special mention goes on for &lt;a href="https://marketplace.visualstudio.com/items?itemName=JeffJorczak.auto-translate-json"&gt;Auto Translate JSON&lt;/a&gt; for VSCode, which allowed me to translate the Intl JSON from English to the other languages.&lt;/p&gt;
&lt;p&gt;But the biggest surprise was &lt;a href="http://tailwindcss.com"&gt;Tailwind CSS&lt;/a&gt;. I&amp;rsquo;ve been bitten many times writing CSS from scratch for this website. I didn&amp;rsquo;t want that pain. Tailwind was amazing, I was able to get the design up fast, responsive and compatible super fast.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-2"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/project_notes_vax_center_finder/vax_site_git_contrib_hu_992c5e6b7ae2340.webp" width="1000" height="394" class="summary-image" alt=""&gt;
	
 &lt;figcaption&gt;Image 2: &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;I was able to get the site up and deployed on &lt;a href="http://Netlify.com"&gt;Netlify&lt;/a&gt; in a couple of days. I hosted it on a &lt;a href="https://vax.covid.ukr.lk"&gt;subdomain&lt;/a&gt; on my personal site.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-3"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/project_notes_vax_center_finder/vax_site_screenshot_hu_69f9096afcbad220.webp" width="1000" height="816" class="summary-image" alt=""&gt;
	
 &lt;figcaption&gt;Image 3: &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 id="aftermath"&gt;Aftermath&lt;/h2&gt;
&lt;p&gt;I shared the link around Twitter and Reddit. It got some &amp;ldquo;decent&amp;rdquo; views and the Analytics showed decent interaction and retention.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-4"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/project_notes_vax_center_finder/vax_site_analytics_1_hu_f1289dfe90333d98.webp" width="1000" height="742" class="summary-image" alt=""&gt;
	
 &lt;figcaption&gt;Image 4: &lt;/figcaption&gt;
&lt;/figure&gt;



&lt;figure id="image-5"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/project_notes_vax_center_finder/vax_site_analytics_2_hu_c68d1098c1aa2dd4.webp" width="1000" height="739" class="summary-image" alt=""&gt;
	
 &lt;figcaption&gt;Image 5: &lt;/figcaption&gt;
&lt;/figure&gt;

In a day or so, I saw a couple of folks have built something similar and much better &lt;a href="https://vaxsl.com/"&gt;vaxsl.com&lt;/a&gt;. They had contact details and helpful resources. Since I didn&amp;rsquo;t have the bandwidth to expand upon I was happy that there was something better!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;This is ultimately the beauty of open data and APIs. They can serve the public to make informed decisions and allow third parties to build experiences that weren&amp;rsquo;t event initially thought of.&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>What "Being Agile" is Really About</title><link>https://ukr.lk/posts/what_being_agile_is_about/</link><pubDate>Sat, 24 Jul 2021 12:18:41 +0000</pubDate><guid>https://ukr.lk/posts/what_being_agile_is_about/</guid><description>&lt;p&gt;The motivation for this article came naturally working on a presentation for my team on engineering process, Agile is playing a big part there. My thought was that this might benefit others as well, if documented here.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/what_being_agile_is_about/wso2fs_hu_e1e59650dcae985d.webp" width="1000" height="663" class="summary-image" alt="Taken at WSO2, Some Time Back"&gt;
	
 &lt;figcaption&gt;Image 1: Taken at WSO2, Some Time Back&lt;/figcaption&gt;
&lt;/figure&gt;

Starting a year back I found my self in an interesting position that requires me to manage engineering for a FinTech SaaS Startup. For us like most startup agility is key, knowing that we can make quick course corrections to fix our trajectory, which always looks like it&amp;rsquo;s not slowing down.&lt;/p&gt;
&lt;h2 id="whats-is-it-anyway"&gt;What&amp;rsquo;s Is it Anyway?&lt;/h2&gt;
&lt;p&gt;To make sure no one is left behind, let me give the quick primer on agile. For this we must travel to the agile temple &lt;a href="http://agilemanifesto.org"&gt;agilemanifesto.org&lt;/a&gt;. This masterpiece of HTML design, outlines the following.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Individuals and interactions&lt;/strong&gt; over processes and tools.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Working software&lt;/strong&gt; over comprehensive documentation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Customer collaboration&lt;/strong&gt; over contract negotiation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Responding to change&lt;/strong&gt; over following a plan.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The main takeaway is the focus of where effort is placed. It&amp;rsquo;s placed to align with the mission and vision of the company. This is not a call to diminish the quality of software and the craft of engineering, but a scope to implement it in.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Agile isn&amp;rsquo;t about getting that certification or using a certain process, It&amp;rsquo;s about doing what&amp;rsquo;s right for your business or cause.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="embodying-the-manifesto"&gt;Embodying The Manifesto&lt;/h2&gt;
&lt;p&gt;The application doesn&amp;rsquo;t stop at a singular level. Some believe that agility takes place in the ideation and development cycle of a product. It&amp;rsquo;s much more than that. &lt;strong&gt;Any surface area that&amp;rsquo;s touched on the process of delivery can benefit from the agile way.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The &amp;ldquo;How?&amp;rdquo; is left vague by the manifesto for a reason. To allow for each adopter to figure out, &lt;strong&gt;as with circumstance there is no one size fits all solution&lt;/strong&gt;. But here are some guidelines to adopt it,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Start with as minimal process as possible,&lt;/strong&gt; expecting a team to adopt a wide gamut of tools and procedures is bound to end in disaster.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Collect Feedback,&lt;/strong&gt; take feedback from the team. Take count of the pain points and wins, Using these make adjustments or alterations to the process.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Coming back to my point on how being agile benefits other facets of your company, The aforementioned procedure is not just scoped to get feedback on how a team operates, but the many artifacts or systems they might interact with.&lt;/p&gt;
&lt;p&gt;For example software design, designing software that allows flexibility and collaboration which preserves agility.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The main takeaway is to know that there is no standard to follow. It&amp;rsquo;s up to you and especially all members of your team to figure out. Hopefully it will stick. If not, don&amp;rsquo;t fret as if you have followed the manifesto, course corrections shouldn&amp;rsquo;t be as daunting.&lt;/p&gt;</description></item><item><title>Social Engineering Isn't Hacking?</title><link>https://ukr.lk/posts/social_engineering_is_hacking/</link><pubDate>Thu, 08 Jul 2021 22:55:40 +0000</pubDate><guid>https://ukr.lk/posts/social_engineering_is_hacking/</guid><description>&lt;p&gt;Recently I picked up a copy of &lt;a href="https://www.amazon.com/Ghost-Wires-Adventures-Worlds-Wanted/dp/0316037729/ref=tmm_pap_swatch_0?_encoding=UTF8&amp;amp;qid=1625783738&amp;amp;sr=8-1"&gt;&amp;ldquo;Ghost in the Wires: My Adventures as the World&amp;rsquo;s Most Wanted Hacker&amp;rdquo;&lt;/a&gt;, for the unaware it&amp;rsquo;s &lt;a href="https://en.wikipedia.org/wiki/Kevin_Mitnick"&gt;Kevin Mitnick&amp;rsquo;s&lt;/a&gt; account of his hacker journey who eventually became “the Darth Vader of the hacking world”. His hacker journey starts with &lt;a href="https://en.wikipedia.org/wiki/Phreaking"&gt;Phone Phreaking&lt;/a&gt; before the dawn of affordable personal computing.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/social_engineering_is_hacking/free_kevin_hu_b854a72f0b4bba6c.webp" width="1000" height="563" class="summary-image" alt="Free Kevin movement stickers, 2600 Magazine"&gt;
	
 &lt;figcaption&gt;Image 1: Free Kevin movement stickers, 2600 Magazine&lt;/figcaption&gt;
&lt;/figure&gt;

What prompted me to write this down was a lowly rated &lt;a href="https://www.goodreads.com/book/show/10256723-ghost-in-the-wires"&gt;GoodReads&lt;/a&gt; review, where the reviewer was unimpressed that the “Hacks” of Kevin Mitnick as he was just “Talking on the phone”&lt;/p&gt;
&lt;p&gt;&lt;em&gt;I was not amused by this. Before I hit that reply button, I decided to explore why some were let down by the Hacks of Kevin Mitnick.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="its-really-magic-at-the-end-of-the-day"&gt;It&amp;rsquo;s really magic at the end of the day&lt;/h2&gt;
&lt;p&gt;The parallel of magic and hacking is one explored constantly throughout the book. I was thrown back to the popular quote on technology and magic,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Any sufficiently advanced technology is indistinguishable from magic.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;a href="https://en.wikipedia.org/wiki/Arthur_C._Clarke"&gt;Arthur C. Clarke&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Personally even as an engineer with the knowledge of fundamental logic that makes a computer tick, some things do catch me off-guard in awe. Especially what man is able to accomplish with bits on digital logic.&lt;/p&gt;
&lt;p&gt;Back to Mitnick, he&amp;rsquo;s first love was magic as well. But, we don&amp;rsquo;t know Kevin as the greatest magician but, as the greatest hacker.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Fooling people with magic was cool. But learning how the phone system worked was fascinating.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;But magic isn&amp;rsquo;t really magic (I&amp;rsquo;ve seen Penn&amp;amp;Teller), It&amp;rsquo;s trickery. Just like what Mitnick did. &lt;strong&gt;A Magician really can&amp;rsquo;t defy physics, but what they can do is bend reality, the lens we see it in. Such as sleight of hand.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="primer-on-social-engineering"&gt;Primer On Social Engineering&lt;/h2&gt;
&lt;p&gt;Social Engineering in basic terms is a psychological manipulation of people into performing actions or divulging confidential information.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Like how magic exploits its weakest link, us and not anything else; It&amp;rsquo;s the same in hacking.&lt;/strong&gt; Kevin was a master at it, he said in the book,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The social-engineering techniques work simply because people are very trusting of anyone who establishes credibility, such as an authorized employee of the company.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I&amp;rsquo;m not going to spoil any of the hacks on this post, if you&amp;rsquo;re interested checkout this &lt;a href="https://www.youtube.com/watch?v=aUqes9QdLQ4"&gt;Google Talk&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="witch-hunt-for-the-first-computer-magician"&gt;Witch-hunt for the first computer magician&lt;/h2&gt;
&lt;p&gt;In an apt sense for the magic parallel, at the end of the line just as a traveling magician, who wooed crowds with some sleight of hand. Is the first to get accused when some anomaly took place.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A traveling performer would amaze the local villagers with tricks and sleights of hand. Because they had no idea how he was doing those tricks, they couldn’t guess at the extent of his abilities. He seemed to have the power to make things appear and disappear at will. That was the point. But if anything went wrong—some cows died, the crops failed, little Sarah got sick—it was all too easy to blame the magician.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Kevin, vilified by the population and the law, was put in solitary confinement for unsafe time spans. Just because people were afraid of the unknown, even the apposition and media going far as saying,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“He can whistle into a telephone and launch a nuclear missile from NORAD,”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The end of the book, takes a truly dark turn as this real-life witch hunt takes place. He was denied bail, and it was a grim outlook.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;the history of the United States had ever been refused a bail hearing. Not the notorious impostor and escape artist Frank Abagnale Jr. Not the serial killer and cannibal Jeffrey Dahmer. Not even the crazed stalker and would-be presidential assassin John Hinckley Jr.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;But he survived, and after a plea agreement, got out and started &lt;a href="https://www.mitnicksecurity.com"&gt;Mitnick Security Consulting&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Ghost in the Wires, great book, read it!&lt;/strong&gt; Some think of hacking as some magical concept, and yes there are clever exploits taking place(in the book). But at the end of the day Kevin was evading the law for fear, because he was misunderstood. And In this context, Social Engineering just works!&lt;/p&gt;
&lt;p&gt;As for the question of “Social Engineering Isn&amp;rsquo;t Hacking?”, With this exploration, I&amp;rsquo;d personally say it is. Mitnick did bring the exploits of social engineering to the limelight, and started a revolution on tightening up security holes in complex systems which involve both computers and humans.&lt;/p&gt;</description></item><item><title>The PC Is Dead, Long Live The PC!</title><link>https://ukr.lk/posts/long_live_the_pc/</link><pubDate>Sat, 26 Jun 2021 13:54:53 +0000</pubDate><guid>https://ukr.lk/posts/long_live_the_pc/</guid><description>&lt;p&gt;Often when frustration hits me with my computing devices, those being an iMac and ThinkPad. I often wonder what my next computing device is going to be. Keeping aside a pledge of reusing my devices, mind often runs hypotheticals with different devices.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/long_live_the_pc/old_desk_hu_c12a8bce962df083.webp" width="1000" height="750" class="summary-image" alt="Current Computing Devices, 2021"&gt;
	
 &lt;figcaption&gt;Image 1: Current Computing Devices, 2021&lt;/figcaption&gt;
&lt;/figure&gt;

It boils down to the following choices,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;iPad Pro with the M1 Chip.&lt;/li&gt;
&lt;li&gt;E-Paper tablet running Android.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These choices are not what traditional power-user devices may look like. I&amp;rsquo;m not alone when it comes to imagining the next personal computing device. There is an ongoing battle on what&amp;rsquo;s will be the next class of personal computing devices.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;It&amp;rsquo;s not necessarily a departure from the PC, but a re-imagination of it.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="precursor-to-personal-computing"&gt;Precursor To Personal Computing&lt;/h2&gt;
&lt;p&gt;Computers were never to be taken lightly, they won wars and put a man on the moon! The imagery created in a mind of boomer/early millennial of computers are large clean rooms with massive units. Attending to these expensive devices are men and women clad in white robes, entering data to these devices using punch-cards or printer-terminals.&lt;/p&gt;
&lt;p&gt;In the late 70s and early 80s, personal computers were the rage. The killer apps came in the form of Spreadsheet apps such as &lt;a href="https://en.wikipedia.org/wiki/VisiCalc"&gt;VisiCalc&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Lotus_1-2-3"&gt;Lotus 1-2-3&lt;/a&gt;. The allure of being able to balance your own checkbook with a computer was really exciting for some. For others gaming and general human curiosity got them.&lt;/p&gt;
&lt;h2 id="personal-computers-are-trucks"&gt;Personal Computers Are Trucks&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m unsure if this is some running gag, but &lt;a href="https://en.wikipedia.org/wiki/Walt_Mossberg"&gt;Walt Mossberg&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Kara_Swisher"&gt;Kara Swisher&lt;/a&gt; hosts of &lt;a href="https://en.wikipedia.org/wiki/All_Things_Digital"&gt;All Things Digital&lt;/a&gt; keep asking Apple folks why the iPad isn&amp;rsquo;t feature rich and general purpose. At the &lt;a href="https://www.cnet.com/news/steve-jobs-at-d8-post-pc-era-is-nigh/"&gt;D8 Conference&lt;/a&gt; late CEO of Apple Computer, &lt;a href="https://en.wikipedia.org/wiki/Steve_Jobs"&gt;Steve Jobs&lt;/a&gt; put forth a great analogy to justify this.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;When we were an agrarian nation, all cars were trucks because that&amp;rsquo;s what you needed on the farms. &amp;hellip; &amp;ldquo;PCs are going to be like trucks,&amp;rdquo; Jobs said. &amp;ldquo;They are still going to be around.&amp;rdquo; However, he said, only &amp;ldquo;one out of &lt;em&gt;x&lt;/em&gt; people will need them.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;- Steve Jobs&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The general purpose computer was really a product of it&amp;rsquo;s time. The thought being that, for the development of a new digital world, people required the heavy lifting trucks(computers).&lt;/p&gt;
&lt;p&gt;Present time, people don&amp;rsquo;t require full-fledged computers to get-by in their every day life. Most workloads of computers for communication and collaboration is achievable via a web-browser. For example using a &lt;a href="https://en.wikipedia.org/wiki/Chromebook"&gt;Chromebook&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="the-mobile-vs-pc-identity-crisis"&gt;The Mobile vs PC Identity crisis&lt;/h2&gt;
&lt;p&gt;Modern mobile computers are great, they are accessible and intuitive. Gone are the baggage of the backwards compatible PC and introduced are touch displays, always connected internet, and a suite of application that is easy to use anywhere!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;My mum loves em! (smartphones) Hates computers, ironic, but a shared sentiment with many.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Tablets taking the place of PC&amp;rsquo;s is an often a debated subject. Let&amp;rsquo;t take Apple&amp;rsquo;s iPad as an example. Apple, is clearly conflicted on it&amp;rsquo;s place in the post-pc era.&lt;/p&gt;
&lt;p&gt;Apple is careful when making the iPad more flexible. In trying to do so, a new line of devices appeared, the iPad Pro. Marketing material talks about how “Your new computer is not a computer”. As for the argument of the iPad Pro, with it&amp;rsquo;s “professionals” focus and high price point, it&amp;rsquo;s more of a luxury device at the moment.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;re: baggage, some PC features are very esoteric. As an example, what would a five-year-old understand if presented with, A tablet or a PC? Would it be the abstract cursor system of a PC or the finger optimized interface on a touch screen? Easy bet on the latter.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="the-re-imagining"&gt;The Re-Imagining&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s clear that a re-invention of the device is required. Let&amp;rsquo;s see what most users are looking for in modern computing devices.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mobility in design and function&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Power Efficiency&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Always Connected&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With these basic factors in mind, It&amp;rsquo;s apparent how the traditional PC suffers on those topics. Traditionally computers weren&amp;rsquo;t required to be mobile and power efficient, the ecosystem is built on a base that&amp;rsquo;s not reflective of how modern devices are used.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;It&amp;rsquo;s not just the hardware that&amp;rsquo;s not suitable, it&amp;rsquo;s the software as well.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Especially, letting go of the mouse is a hard one, that&amp;rsquo;s where most of the UX issues for touch crop-up. A decrease of input resolution needs to be considered.
I believe, device manufacturers are taking the correct step for forking of mobile operating systems and hardware as the aforementioned points are addressed from the get-go.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The PC will be present in the future. But its usage will be left for specialist workflows. Most standard productivity and learning can be accomplished with the likes of a tablet. This will make the many facets of computing accesible 🤞.&lt;/p&gt;
&lt;p&gt;In retrospective, &lt;a href="https://en.wikipedia.org/wiki/Windows_8"&gt;Windows 8 Tablets&lt;/a&gt; were bridge devices! Which were able to operate on in touch mode but was still able to be standard PC. Unfortunatley that didn&amp;rsquo;t pan out well, maybe Windows 11 will achieve that.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;So what&amp;rsquo;s my dream computing device going to be? I&amp;rsquo;ll wait for now&amp;hellip;&lt;/em&gt;&lt;/p&gt;</description></item><item><title>Pragmatic Approach : Serverless For Startups</title><link>https://ukr.lk/posts/serverless_for_startups/</link><pubDate>Wed, 23 Jun 2021 07:00:26 +0000</pubDate><guid>https://ukr.lk/posts/serverless_for_startups/</guid><description>&lt;p&gt;Late last-year(June 2020) I spoke about Serverless on &lt;a href="https://techkatha.com/page/9/"&gt;TechKatha (Sri Lankan Tech Podcast)&lt;/a&gt;. From that point I&amp;rsquo;ve been asked, countless times, why we(new startup I joined) chose Serverless? The weight of the selection didn&amp;rsquo;t fall on technical details as most would assume. It was much more pragmatic.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/serverless_for_startups/yamu_cmb_2017_hu_43a951fb35dad743.webp" width="1000" height="675" class="summary-image" alt="Colombo, Sri Lanka 2017, Office Of YAMU"&gt;
	
 &lt;figcaption&gt;Image 1: Colombo, Sri Lanka 2017, Office Of YAMU&lt;/figcaption&gt;
&lt;/figure&gt;

Who is this article for?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Engineering Leads&lt;/strong&gt;, interested in adopting serverless.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Software Developers&lt;/strong&gt;, who want to understand the pros/cons of serverless.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This write-up will explore serverless compute and how it benefits startups with reasoning, key points and anecdotal experiences.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2019, End of December I decided to leave my engineering job at &lt;a href="https://wso2.com/solutions/finance/"&gt;WSO2&lt;/a&gt;. What caught my interest was an opportunity of a green-field project to help build a financial SaaS platform.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="agility-is-key"&gt;Agility is key&lt;/h2&gt;
&lt;p&gt;Technology startups are many, Ideas are never concrete from the get-go. A lot of &lt;strong&gt;wiggle room and agility required to enable quick course corrections.&lt;/strong&gt; The ultimate goal is to quickly get it out to the intended audience.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I have seen the same cycle again and again — great products are created through small teams, with great leaders, who eliminate all non-critical features, while working under extreme pressure, and produce a product that just barely works.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;a href="https://en.wikipedia.org/wiki/Eric_Schmidt"&gt;Eric Schmidt&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;My boss put me on to this quote by Eric Schmidt. And it re-enforces the thought on why It&amp;rsquo;s important to be agile in certain scenarios. This sentiment played a huge role in the selection of serverless.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;When ultimately I joined in 2020 January, what was present in the company IP was a mock-up. With the heavy burden of specific domain knowledge, our team bound to be minimal. For us, time best-spent is on iteratively exploring and building the product.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;In the beginning, my mind was set on using &lt;a href="https://en.wikipedia.org/wiki/Kubernetes"&gt;k8s&lt;/a&gt; micro-services with an &lt;a href="https://istio.io"&gt;istio(Service Mesh)&lt;/a&gt;. But it was apparent with our small team of polyglot developers, It&amp;rsquo;s not worth investing time in setting up such a solution.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="what-is-serverless"&gt;What is Serverless?&lt;/h2&gt;
&lt;p&gt;One major thing out of the way, there are servers. But they are not to be worried about, is the takeaway. I think of serverless more as a cloud native application runtime.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Cloud native technologies empower organizations to build and run scalable applications in modern, dynamic environments such as public, private, and hybrid clouds.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/cncf/foundation/blob/master/charter.md"&gt;The CNCF Cloud Native Definition v1.0&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s the most cloud native one can be, a manged service for your code. Advantages of serverless are as following,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Focus on code&lt;/strong&gt;, not Infrastructure.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pay only for usage&lt;/strong&gt;. No cost incurred for idle-time.&lt;/li&gt;
&lt;li&gt;Certain workloads that require &lt;strong&gt;parallel processing&lt;/strong&gt; is much more cost-effective.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Better Developer Experience (DX)&lt;/strong&gt; with integrated insights and bindings to commonly used components.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;My job as the engineering-owner became getting out of the way of the development team. Therefore, ultimately allowing them to iterate on the product. &lt;strong&gt;While making sure resilience and quality stays consistent&lt;/strong&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Paired with serverless and DevOps, we were off to the races. After the initial proof of concepts iterated and scrutinized. We finally saw maturity in the product that lead for the road maps to be laid out by the end of 2020. Trajectory was visible!&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="pros-of-serverless"&gt;Pros Of Serverless&lt;/h2&gt;
&lt;p&gt;While there are many advantages in choosing serverless, especially with its tight integration with cloud services. I&amp;rsquo;d argue the following four trumps as the main pros of serverless.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Resilience&lt;/strong&gt; - Apart from the up-time and production readiness, even in areas such as events/messaging infrastructure.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Distributed Tracing&lt;/strong&gt; - From the user hitting a button on a web interface to the database, tracing is auto-instrumented in most cases.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No Boilerplate&lt;/strong&gt; - With infrastructure being cloud native, code written is for the business use-case. With use of native bindings, common function/component integrations are present.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Yes, these are achievable through traditional means in any stack. &lt;strong&gt;But commendable is having the aforementioned capabilities from day one.&lt;/strong&gt; This aforementioned capabilities allow teams to iterate on software fast while getting performance data back to developers for further tuning.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2021 was exciting, development was steady on and by March we had already delivered an MVP. We built DevOps templates and &lt;a href="https://en.wikipedia.org/wiki/Infrastructure_as_code"&gt;IaC&lt;/a&gt; modules to help deployment, which removed the last fiction points. The MVP was well-received, and had the feedback to steer the plan in the correct direction.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="cons-of-serverless"&gt;Cons Of Serverless&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Selecting the correct tool for the job comes first&lt;/strong&gt;, some forms of compute may not benefit serverless because of the following,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cold Starts&lt;/strong&gt; - Because Serverless has no long-running instances and prefer dynamic scaling up and down from zero, the initial request in a session will have startup delays.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Predictable Workloads&lt;/strong&gt; - Serverless is designed for dynamic workloads, not for static and especially long-running workloads, the latter not supported by some vendors in specific plans.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vendor Lock-In&lt;/strong&gt; - Serverless allows cloud providers to give great integration to cloud native services, which gives value but ultimately locks you in.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Problems such as Cold Starts can be alleviated to a certain extent. Using log-in events to pre-warm instances is one simple example.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;We had encounted our own problems with serverless, some caused by programming for it, traditionally not harnessing its native bindings. But most were time-outs and complaints of cold-starts. With metrics and user-feedback, design changes applied to make-sure pre-warming is done. Some workloads optimized or moved to VMs that did not benefit from serverless.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The standard caveat applies, “Your millage may vary”. Given our constraints with resourcing, serverless helped us to quickly get things off the ground.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;With more sprints, new features introduced and maintained. No major roadblocks faced. We were given the opportunity to accelerate and deliver our product. Currently standing at a respectable version one.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The value gained by our team(for serverless) is being able to put most of our time on the core product, and not worry about Infrastructure.&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Special thanks to my team, as this was not a singular journey at all. Truly a dream team!&lt;/em&gt;&lt;/p&gt;</description></item><item><title>RSS Feed for next.js blog</title><link>https://ukr.lk/posts/rss_feed_nextjs/</link><pubDate>Sat, 19 Jun 2021 17:12:26 +0000</pubDate><guid>https://ukr.lk/posts/rss_feed_nextjs/</guid><description>&lt;p&gt;This blog finally has an RSS feed, I welcome you to 1999. When building my own blog instead of using a blogging platform I knew I was getting into a world of pain.&lt;/p&gt;
&lt;p&gt;Most of the site is complete and usable, but what lacked was an RSS feed for potential followers to subscribe with! Let&amp;rsquo;s leave the talk and get-into it!&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-2"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/rss_feed_nextjs/cmb_np_hu_6b20976740634882.webp" width="1000" height="675" class="summary-image" alt="Colombo, Sri Lanka 2017, Newspaper Stand"&gt;
	
 &lt;figcaption&gt;Image 2: Colombo, Sri Lanka 2017, Newspaper Stand&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 id="npm-dependencies"&gt;NPM Dependencies&lt;/h2&gt;
&lt;p&gt;We&amp;rsquo;ll have to install a new package aptly named &lt;a href="https://www.npmjs.com/package/rss"&gt;rss&lt;/a&gt; for making it easy to generate the RSS feed. Why reinvent the wheel, eh?&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;yarn add rss @types/rss
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;note: I added &lt;code&gt;@types/rss&lt;/code&gt; as my next.js project is in typescript&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="making-a-fake-route"&gt;Making A Fake Route&lt;/h2&gt;
&lt;p&gt;This is probably the point some might have scratched their heads. How can we create a custom dynamic file during build time?&lt;/p&gt;
&lt;p&gt;There is no easy way, but this hack works perfectly. &lt;strong&gt;Create a new file in pages&lt;/strong&gt; named something like &lt;code&gt;static_file_build.tsx&lt;/code&gt; (Easter Egg!)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What we will make this route do is,&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Render Dummy Page.&lt;/li&gt;
&lt;li&gt;Load Latest Post Details.&lt;/li&gt;
&lt;li&gt;Write a XML string to a file.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;This file serves no display purpose but to ber an entry point to build our rss feed.&lt;/em&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ts" data-lang="ts"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fs&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;fs&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;DummyPage&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; () &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Dummy Page&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;buildRss&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;posts&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;PostEntity&lt;/span&gt;[])&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// TODO;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;getStaticProps&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; () &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Depends On Your Implementation
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;posts&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;PostAPI&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getLatest&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Generate Feed XML
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;feedXml&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;buildRss&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;posts&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Write Generated RSS Feed To Public Folder
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fs&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;writeFileSync&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;public/rss.xml&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;feedXml&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;props&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;posts&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;default&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;DummyPage&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As shown above, it&amp;rsquo;s clear how this works. Depending on your backend get your latests posts loaded and let&amp;rsquo;s get cracking on building the feed!&lt;/p&gt;
&lt;h2 id="building-the-feed"&gt;Building The Feed&lt;/h2&gt;
&lt;p&gt;Now this is where the installed &lt;code&gt;rss&lt;/code&gt; package comes to the rescue. It has an easy interface/api to build the feed and export the xml. Let&amp;rsquo;s complete the buildRss function!&lt;/p&gt;
&lt;h3 id="create-feed-object"&gt;Create Feed Object&lt;/h3&gt;
&lt;p&gt;The first task is to create the feed object. It should be instantiated with your basic site details.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ts" data-lang="ts"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;feed&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;RSS&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;title&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Kaveen R&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;description&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;blog posts&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;feed_url&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;process&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;env&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;BASE_URL&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/rss.xml`&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;site_url&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;process&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;env&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;BASE_URL&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;pubDate&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Date()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="add-posts-to-feed-object"&gt;Add Posts To Feed Object&lt;/h3&gt;
&lt;p&gt;Next task is to iterate through all your blog posts and add them to the aforementioned feed object.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ts" data-lang="ts"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Add Each Post to feed
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;posts&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;forEach&lt;/span&gt;((&lt;span style="color:#a6e22e"&gt;post&lt;/span&gt;)&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Take Markdown Content &amp;amp; Convert To basic HTML
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;body&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ReactDOMServer&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;renderToStaticMarkup&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;ReactMarkdown&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;escapeHtml&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;source&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;post&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;content&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; );
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;feed&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;item&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;title&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;post.matter.title&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;description&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;body&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;url&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;process&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;env&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;BASE_URL&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/posts/&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;post&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;matter&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;slug&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;date&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;post.matter.date&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;category&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;post.matter.categories&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;author&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Kaveen R&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Important Notes&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;description&lt;/code&gt;&lt;/strong&gt; should contain an HTML representation of your blog post content. Buy invoking &lt;code&gt;ReactDOMServer.renderToStaticMarkup()&lt;/code&gt; we&amp;rsquo;re generating HTML for a given React component. &lt;strong&gt;This will change with the libraries you use&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;categories&lt;/code&gt;&lt;/strong&gt; is a list of unique strings, when using customizable RSS readers users can filter your latests post using the mentioned catagories.&lt;/p&gt;
&lt;h3 id="serializing-the-feed"&gt;Serializing The Feed&lt;/h3&gt;
&lt;p&gt;Last step is to convert the feed object into an XML string which will be written to file by our dummy page!&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-tsx" data-lang="tsx"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;feed&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;xml&lt;/span&gt;({&lt;span style="color:#a6e22e"&gt;indent&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now when building your page you&amp;rsquo;ll see that feed is generated an place on &lt;code&gt;/public/rss.xml&lt;/code&gt;!&lt;/p&gt;
&lt;h2 id="housekeeping"&gt;Housekeeping&lt;/h2&gt;
&lt;p&gt;There are a couple of more things to do! We ant to make sure that our RSS feed is complaint and also can be found by feed readers. This is how to quickly do that&lt;/p&gt;
&lt;h3 id="checking-for-feed-errors"&gt;Checking For Feed Errors&lt;/h3&gt;
&lt;p&gt;To Make Sure we deliver the best RSS feed to all users, we can validate it using a tool such as &lt;a href="https://validator.w3.org/feed/"&gt;W3 Validator&lt;/a&gt; which will validate and give suggestions on how to make the feed better.&lt;/p&gt;
&lt;h3 id="making-sure-the-feed-is-discoverable"&gt;Making Sure The Feed Is Discoverable&lt;/h3&gt;
&lt;p&gt;On one of your main next.js template(such as &lt;code&gt;_app.ts&lt;/code&gt;) include the following in the header, this meta tag will guide compatible software to the feed.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;Head&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;link&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;rel&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;alternate&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;type&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;application/rss+xml&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;title&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;RSS&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;/rss.xml&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;Head&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="adding-rssxml-to-gitignore"&gt;Adding &lt;code&gt;rss.xml&lt;/code&gt; to gitignore&lt;/h2&gt;
&lt;p&gt;This is to anyone who is using GIT VSC. To avoid commiting the RSS file to VCS accidentally add the feed reference to the &lt;code&gt;.gitignore&lt;/code&gt; file.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public/rss.xml
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That&amp;rsquo;s it folks! Now you got a RSS Feed for your blog. It maybe 22 years too late, but at-least we got it!&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="complete-code-sample"&gt;Complete Code Sample&lt;/h2&gt;
&lt;p&gt;Here is the complete code sample which we ran through today!&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-tsx" data-lang="tsx"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fs&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;fs&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;RSS&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;rss&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ReactDOMServer&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;react-dom/server&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ReactMarkdown&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;react-markdown&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;DummyPage&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; () &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Dummy Page&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;buildRss&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;posts&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;PostEntity&lt;/span&gt;[])&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Create Feed With Site Details
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;feed&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;RSS&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;title&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Kaveen R&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;description&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;blog posts&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;feed_url&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;process&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;env&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;BASE_URL&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/rss.xml`&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;site_url&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;process&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;env&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;BASE_URL&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;pubDate&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Date()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Add Each Post to feed
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;posts&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;forEach&lt;/span&gt;((&lt;span style="color:#a6e22e"&gt;post&lt;/span&gt;)&lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Take Markdown Content &amp;amp; Convert To basic HTML
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;body&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ReactDOMServer&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;renderToStaticMarkup&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;ReactMarkdown&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;escapeHtml&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;source&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;post&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;content&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; );
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;feed&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;item&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;title&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;post.matter.title&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;description&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;body&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;url&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;process&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;env&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;BASE_URL&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/posts/&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;post&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;matter&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;slug&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;date&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;post.matter.date&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;category&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;post.matter.categories&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;author&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Kaveen R&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Serialize Feed &amp;amp; Return as string
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;feed&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;xml&lt;/span&gt;({&lt;span style="color:#a6e22e"&gt;indent&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;getStaticProps&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; () &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Depends On Your Implementation
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;posts&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;PostAPI&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getLatest&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Generate Feed XML
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;feedXml&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;buildRss&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;posts&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Write Generated RSS Feed To Public Folder
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fs&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;writeFileSync&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;public/rss.xml&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;feedXml&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;props&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;posts&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Life And How To Live It</title><link>https://ukr.lk/posts/life_and_how_to_live_it/</link><pubDate>Thu, 17 Jun 2021 17:12:26 +0000</pubDate><guid>https://ukr.lk/posts/life_and_how_to_live_it/</guid><description>&lt;p&gt;Despite human&amp;rsquo;s living on this earth for many millennia. I&amp;rsquo;m baffled how, regardless of the many achievements we&amp;rsquo;ve made, there is no definite guide to live. Where is my “Life And How To Live It&amp;quot; book? It&amp;rsquo;s a silly thought. Understood is that fact, the human experience is not one size fits all. It changes with upbringing, circumstance and ultimately perception. What if I told you there is such a book?&lt;/p&gt;
&lt;p&gt;The phrase stuck with when I heard “Life and how to live it”. It&amp;rsquo;s a song by undoubtedly one of the best bands of all-time, R.E.M. Apart from the beauty of R.E.M&amp;rsquo;s lyrics, the beauty of the story behind this song is inspiring!&lt;/p&gt;
&lt;iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/DJJwjE2TG6Q" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;The lyrics talk about a man named &lt;a href="https://web.archive.org/web/20150417234837/http://onlineathens.com/rem-hall/stories/glossary.shtml"&gt;Brivs Mekis&lt;/a&gt;. Quoted to be a mentally disturbed (some sources say a schizophrenic) individual from R.E.M&amp;rsquo;s hometown in Athens, Ga. He had two homes next to each other, which were connected through a hole he made in his wall.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Burn bright through the night, two pockets lead the way&lt;br&gt;
Two doors to go between the wall was raised today&lt;br&gt;
Two doors, two names to call your others and your own
Keep these books well stocked away and take your happy home&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;&amp;ndash;R.E.M&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;As the lyrics go, Brivs self-published a book titled &lt;strong&gt;“Life: How to Live.”&lt;/strong&gt;. He also held all the copies oh his own book. R.E.M&amp;rsquo;s Micheal Stipe would often divulge these facts during his &lt;a href="https://www.youtube.com/watch?v=2VsGgnQSl1I"&gt;pre-performance banter&lt;/a&gt; at shows.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The unconventionality and the humility of this whole matter often catches me in awe.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/life_and_how_to_live_it/galle_outlook_hu_3a2103432696621a.webp" width="1000" height="663" class="summary-image" alt="Galle, Sri Lanka 2018, Looking out"&gt;
	
 &lt;figcaption&gt;Image 1: Galle, Sri Lanka 2018, Looking out&lt;/figcaption&gt;
&lt;/figure&gt;

I&amp;rsquo;m afraid I can&amp;rsquo;t tell you how to live life.
“Life and how to live it” is a book that we all must write ourselves.&lt;/p&gt;
&lt;p&gt;There must be a reason why Brivs chose to stock his bookshelf instead of giving it to others. It&amp;rsquo;s what you make it to be. You owe no one to measure up to any pre-set benchmarks.&lt;/p&gt;
&lt;p&gt;I wish you a good day, and hope you find what ever you may seek.&lt;/p&gt;</description></item><item><title>Conformity &amp; The Internet</title><link>https://ukr.lk/posts/conformity_and_the_internet/</link><pubDate>Wed, 16 Jun 2021 17:12:26 +0000</pubDate><guid>https://ukr.lk/posts/conformity_and_the_internet/</guid><description>&lt;p&gt;I feel foolish yearning for the days of the web I never experienced. My journey to the web started with Broadband internet. I was privileged to have the bandwidth to take Skype calls with best friends after School, watch Angry Video Game Nerd on YouTube and wage war on Tumblr.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/conformity_and_the_internet/sg_water_hu_92611e06f5ed532c.webp" width="1000" height="670" class="summary-image" alt="Singapore 2018, Reflections"&gt;
	
 &lt;figcaption&gt;Image 1: Singapore 2018, Reflections&lt;/figcaption&gt;
&lt;/figure&gt;

My experience with the internet and computers has been bittersweet(Surprising as I do sound like the biggest dork in town). My personal computer-hobbyist goal has always been to expand human experience. Not to use it exclusively as an aid or tool, as that would be doing a disservice to ourselves.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Computers are like a bicycle for the mind.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Quote by &lt;a href="https://en.wikipedia.org/wiki/Steve_Jobs"&gt;Steve Jobs&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="web-10--early-days"&gt;Web 1.0 — Early Days&lt;/h2&gt;
&lt;p&gt;Before that, way before that, I might add. In 1996, &lt;a href="https://en.wikipedia.org/wiki/John_Perry_Barlow"&gt;John Barlow,&lt;/a&gt; lyricist and essayist, publishes &lt;a href="https://www.eff.org/cyberspace-independence"&gt;A Declaration of the Independence of Cyberspace&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We are creating a world where anyone, anywhere may express his or her beliefs, no matter how singular, without fear of being coerced into silence or conformity.
Your legal concepts of property, expression, identity, movement, and context do not apply to us.They are all based on matter, and there is no matter here.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;John Barlow&amp;rsquo;s vision for cyberspace was a grand one that transcended physical existence and into a new digital unknown. John Barlow was a founding member of the &lt;a href="https://www.eff.org/"&gt;EFF&lt;/a&gt;, also a member of the band &lt;a href="https://en.wikipedia.org/wiki/Grateful_Dead"&gt;Grateful Dead&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;This school of thought shaped the web to build a deeply personal experience on the web. These netizens took the browser as their canvas and laid out some HTML masterpieces!&lt;/p&gt;
&lt;p&gt;&lt;a href="https://digital-archaeology.org/wp-content/uploads/2014/01/Geocities_blog.jpg"&gt;

&lt;figure id="image-2"&gt;
	
 &lt;figcaption&gt;Image 2: GeoCities screenshots captured from Olia Lialina and Dragan Espenschied’s Tumblr ‘One Terabyte of Kilobyte Age’.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can take a glimpse of the old web through &lt;a href="https://oneterabyteofkilobyteage.tumblr.com"&gt;# One Terabyte of Kilobyte Age&lt;/a&gt; by Olia Lialina and Dragan Espenschied.&lt;/p&gt;
&lt;h2 id="web-20--the-trojan-horse"&gt;Web 2.0 — The Trojan Horse&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Web_2.0"&gt;Web 2.0&lt;/a&gt; itself is a departure from the original vision that John Barlow had. Where the early web consisted of users creating their own siloed webspaces, The Web 2.0 saw the rise of SaaS(Software as a Service).&lt;/p&gt;
&lt;p&gt;Standardization and interoperability was another aspect that Web 2.0 emphasized on. Interoperability itself can be classified as conformity/conformance, but let&amp;rsquo;s forget that. It was a golden age, this climate brought us APIs. With which interconnected many systems to build new experiences.&lt;/p&gt;
&lt;p&gt;The increasing of speed and being always online, the old personal websites of custom HTML and simple guest books (How skeumorphic of us) felt dated. With the influx of new users with varying degrees of computer literacy, social media platforms win with their accessibility.&lt;/p&gt;
&lt;h2 id="present-day--present-time"&gt;Present Day — Present Time&lt;/h2&gt;
&lt;p&gt;I can only speak for myself. With the penetration of social media and it&amp;rsquo;s integration to modern-day life, for some it has become a necessity to navigate their life. What was once a pastime activity of dialing-in became an integration into our daily lives. We carry always-connected computers in our pockets!&lt;/p&gt;
&lt;p&gt;In the context of John Barlow&amp;rsquo;s essay, the current internet transformed from a bazaar to a zoned theme park. This reminds of the popular opening lyric of &lt;em&gt;“Big Yellow Taxi”,&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;They paved paradise&lt;br&gt;
And put up a parking lot&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Lyrics by &lt;a href="https://jonimitchell.com/music/song.cfm?id=13"&gt;Joni Mitchell&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;It became one-size fits all&lt;/strong&gt;, but that&amp;rsquo;s okay as it came the ability to re-invent ourselves. The ability to change one&amp;rsquo;s image to conform into the ideals of the masses. An action as simple as &lt;em&gt;liking&lt;/em&gt; or &lt;em&gt;retweeting&lt;/em&gt; may seem innocent enough, but the consequences are unimaginable in a huge social echo-chamber. What may start as a compliance, to not be left in the digital dust of social media, is bound to get internalized.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The underlying human code that pushes us to communicate and connect will find a way! It may come as you&amp;rsquo;re surfing a trend trying to catch engagement or being influenced by targeted ads during hard times.&lt;/p&gt;
&lt;p&gt;Most users have caught up with the ploys of the modern web that hacks our minds for engagement. With real life revolutions, wars, the good and the bad. The power of what&amp;rsquo;s in our hands is being understood now.&lt;/p&gt;
&lt;p&gt;Used as a tool, it can be powerful. But with it comes the standard disclaimer, tools blunt or not can inflict harm. Social media in the hands of the nefarious can lead to disasters. &lt;strong&gt;There&amp;rsquo;s a huge gap left in social psychology to be explored on social media&amp;rsquo;s influence on us.&lt;/strong&gt; &lt;a href="https://onlinelibrary.wiley.com/doi/abs/10.1002/ejsp.2097"&gt;(Kende et al., 2015)&lt;/a&gt;&lt;/p&gt;</description></item><item><title>How Spotify Streaming Farms Hurt Independent Musicians</title><link>https://ukr.lk/posts/spotify_streaming_farms/</link><pubDate>Sun, 13 Jun 2021 17:12:26 +0000</pubDate><guid>https://ukr.lk/posts/spotify_streaming_farms/</guid><description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note: This is not new knowledge or breaking news. As informed consumers of music during the pandemic, It&amp;rsquo;s important to understand how Spotify works. Most importantly how it might not help to just stream your favorite indie band.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Farms… The word conjures up images of vistas of green, red tractors and barns. Today most of it stays the same. Let&amp;rsquo;s forget about the unfixable tractors because of Software IP Rights (Tangent Alert!). We&amp;rsquo;re talking about the other farms, power-hungry warehouses running warm with computer and phones pretending to be humans.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/spotify_streaming_farms/sg_records_hu_b8ab1b1b722c2fb2.webp" width="1000" height="737" class="summary-image" alt="Singapore 2018, Record Store In China Town"&gt;
	
 &lt;figcaption&gt;Image 1: Singapore 2018, Record Store In China Town&lt;/figcaption&gt;
&lt;/figure&gt;

With that context in mind “Spotify Stream Farms” for lack of a better word felt “innocent” enough. A bunch of bad actors wanting to get their subpar organized-noise(music) to the limelight. Some might even shrug it off, blaming it on the &lt;em&gt;“system”&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id="the-business-model"&gt;The Business Model&lt;/h2&gt;
&lt;p&gt;Streaming farms, sounded unsurprising until I got to know about how bad actors are making bank by exploiting Spotify.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note: This write-up will only explore parts of the model that is important for this article, and is simplified for brevity.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Spotify operates on a basic freemium model with the majority of the consumers being subscribers of the service. Let&amp;rsquo;s explore how creators get paid, In Summary Spotify earns money by splitting their total “revenue” (subscription or ads) in a 30%, 70% split.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;30%&lt;/strong&gt; → To Spotify.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;70%&lt;/strong&gt; → To The Creators (based on listens, a listen constitutes 30s of playback)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;“Sounds great?”&lt;/em&gt; Well I thought myself as well, until read I how &lt;strong&gt;the top 1.4% artists generated 90% of the streams on the platform therefore the remaining 98.6% made 10%&lt;/strong&gt;. That&amp;rsquo;s 2,957,000 Artists getting 10% of the total! (2020 Q2 Report Spotify)&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s a tough space is an understatement for an independent artist. Worsen if not taken by mass appeal.&lt;/p&gt;
&lt;h2 id="stream-farms-adding-insult-to-injury"&gt;Stream Farms, Adding Insult To Injury&lt;/h2&gt;
&lt;p&gt;As hinted prior, stream farms are not just for inflating listens(bumping the artist up), It&amp;rsquo;s a way to generate money. Musician nor not regardless, a bad actor can easily publish stock music on to the platform and get the bots to ear in.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Outline on how this kind of operation would run,&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Procure a number of fake Spotify accounts (using phishing or creating) and install on a bank of phones.&lt;/li&gt;
&lt;li&gt;Publish music under a fake artist name.&lt;/li&gt;
&lt;li&gt;Get a bank of phones or computers to listen to the fake published music.&lt;/li&gt;
&lt;li&gt;Voilà, now you get to take a part of the Spotify revenue pool.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note On Stolen Accounts: Many have complained on how there are random listens in their accounts when inactive, this is the case of phished accounts used for this ploy. Think twice before buying a Spotify Subscription From eBay!&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Now let&amp;rsquo;s put this practice into context. Spotify&amp;rsquo;s still keeps it&amp;rsquo;s 30% The bots holding more of the listens will get a better payout. In this case, the honest artists are left to suffer.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Statements by Spotify talks about cracking down on bad actors. The goal is to make the platform a better place for all stakeholders. Some claim that the mainstream music industry also plays a part to better promote upcoming artists. I&amp;rsquo;m going to refrain on commenting on it&amp;rsquo;s progress due to the lack of research.&lt;/p&gt;
&lt;p&gt;But, I hope this write-down helps you to navigate the streaming business with caution. Most independent make their money through gigging and direct sales, which is curbed with the pandemic. Help your local independent artists!&lt;/p&gt;</description></item><item><title>Trust The Process Of Creativity</title><link>https://ukr.lk/posts/the_process_of_creativity/</link><pubDate>Fri, 11 Jun 2021 17:12:26 +0000</pubDate><guid>https://ukr.lk/posts/the_process_of_creativity/</guid><description>&lt;p&gt;At times when it comes to explaining my personal process for problem-solving I get anxious. Not because I&amp;rsquo;m about to spew some disingenuous idea but the fact how uninvolved it sounds.&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://ukr.lk/posts/the_process_of_creativity/cr3_thumb.jpg"&gt;
&lt;/figure&gt;

&lt;h2 id="the-process"&gt;The Process&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;“Uninvolved?”&lt;/em&gt; you may ask, let me explain in brief. It starts with observing the problem, and then I do &lt;strong&gt;nothing-at-all&lt;/strong&gt;… Given a bit or a-lot of time I&amp;rsquo;d be presented with a solution, or in most cases an approach that leads to the solution.&lt;/p&gt;
&lt;p&gt;Yes it does sound underwhelming, it doesn&amp;rsquo;t sound like a process at all. Until a couple of days I was baffled and frankly ashamed by this. That&amp;rsquo;s the point I discovered “Four Stages Of Control”.&lt;/p&gt;
&lt;h2 id="four-stages-of-control"&gt;Four Stages Of Control&lt;/h2&gt;
&lt;p&gt;“Four Stages Of Control” is a formalized creative process penned by psychologist Graham Walla in his 1926 book “The Art Of Thought”. Unlike what common-sense might dictate, his model spans the process in both action and inaction(more on this later). These are the four stages.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Preparation&lt;/strong&gt; → Focus and attention paid to the subject.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Incubation&lt;/strong&gt; → Leaving the subject to let it absorb passively.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Illumination&lt;/strong&gt; → The sudden moment of insight!&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Verification&lt;/strong&gt; → Verifying illumination and producing work.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Preparation&lt;/em&gt; and &lt;em&gt;Verification&lt;/em&gt; is quite understandable. Take for example the context of writing. Preparation is the research of a topic and verification is the end-of-the-line where verifying facts and editing takes place. What personally got me in awe was that the stages of &lt;em&gt;Incubation&lt;/em&gt; and &lt;em&gt;Illumination&lt;/em&gt; can take place and by rule &lt;em&gt;Incubation&lt;/em&gt; will &lt;strong&gt;take place out of the creative stint&lt;/strong&gt;. This means you can be sleeping, having breakfast, etc.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Now it doesn&amp;rsquo;t feel so bad to say “sleep on it” at times!&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Yes, this is not a solid framework with the presented facts here. Furthermore, reading this through my engineering glasses sounds preposterous! Which is understandable as that rely on many patterns and rules set in place.&lt;/p&gt;
&lt;p&gt;But what is understandable(personally) is giving space to process the knowledge without additional noise or bias. So if you feel like you&amp;rsquo;re in a creative rut, try to separate your concerns of hitting the end results. Dive into some good material and sleep on it!&lt;/p&gt;</description></item><item><title>Dynamic DNS Using Azure DNS Zones And Logic Apps</title><link>https://ukr.lk/posts/azure-dyn-dns/</link><pubDate>Sun, 25 Apr 2021 14:42:46 +0000</pubDate><guid>https://ukr.lk/posts/azure-dyn-dns/</guid><description>&lt;p&gt;Due to some circumstances I wasn&amp;rsquo;t happy with my DNS setup, which was very basic I used Netlify DNS &amp;amp; as for Dynamic DNS, I used duckdns.org as a CNAME to a subdomain, which worked really well. My only gripe was downtimes with DuckDNS.&lt;/p&gt;
&lt;p&gt;When searching for a Dynamic DNS solution I was a bit blown away by the subscription prices. Instead I decided to use my most comfortable cloud provider, that being Azure.&lt;/p&gt;
&lt;h2 id="requirements"&gt;Requirements&lt;/h2&gt;
&lt;p&gt;To make sure there is none of that inevitable scope creep I wrote down a list of requirements that I need to fullfil.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Functional:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;One Stop Shop For all DNS management for domain.&lt;/li&gt;
&lt;li&gt;Dynamically update subdomain &amp;amp; wildcard subdomain records.&lt;/li&gt;
&lt;li&gt;Be able to dynamically set local IP Address using cron.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Non-Functional:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cheap!&lt;/li&gt;
&lt;li&gt;Easy to maintain // low-or-no-code.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="part-1---general-dns-management"&gt;&lt;strong&gt;Part 1&lt;/strong&gt; - General DNS Management.&lt;/h2&gt;
&lt;p&gt;This was simple, setting up &lt;a href="https://docs.microsoft.com/en-us/azure/dns/dns-getstarted-portal"&gt;Azure DNS Zones&lt;/a&gt; was straight forward with which I was able to quickly setup my website &amp;amp; email DNS records.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/azure-dyn-dns/az_dyn_zone_hu_236fb684e03e9cb6.webp" width="1000" height="688" class="summary-image" alt="Azure DNS Zones Screenshot"&gt;
	
 &lt;figcaption&gt;Image 1: Azure DNS Zones Screenshot&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 id="part-2---dynamic-dns-mechanism"&gt;&lt;strong&gt;Part 2&lt;/strong&gt; - Dynamic DNS Mechanism.&lt;/h2&gt;
&lt;p&gt;Dynamic DNS is not provided by Azure :( But dynamic DNS is no voo-doo magic, it&amp;rsquo;s simply a DNS record with a low TTL(time to live). In simple terms if you manually update the entry on the Azure DNS portal with a low TTL that gets the job done.&lt;/p&gt;
&lt;p&gt;But we don&amp;rsquo;t want to do that, I have seen a couple of DynDNS solutions using Azure Functions, but personally that felt too overkill. I was lazy and I need the easy way out! &lt;strong&gt;The Solution is &lt;a href="https://docs.microsoft.com/en-us/azure/logic-apps/logic-apps-overview"&gt;Azure Logic Apps&lt;/a&gt;&lt;/strong&gt;, Logic Apps are simply code-less event based functions that can be designed on the portal.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-2"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/azure-dyn-dns/az_dyn_la_hu_ebb79788e0fa57e3.webp" width="1000" height="688" class="summary-image" alt="Azure Logic App for Dynamic DNS Updating"&gt;
	
 &lt;figcaption&gt;Image 2: Azure Logic App for Dynamic DNS Updating&lt;/figcaption&gt;
&lt;/figure&gt;

Shown above is the Azure Logic App that does the dynamic DNS updating. This is archived using the latest preview feature ARM Deploy, ARM being Azure Resource Manager which under the hood manges all Azure resources. This Logic App Does the following,&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Accepts HTTP Post Requests using a secured endpoint.&lt;/li&gt;
&lt;li&gt;Takes IP address given in request and updates Azure DNS subdomain A records.&lt;/li&gt;
&lt;li&gt;Responds with deployment status.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;given below is the code view of my logic app. &lt;em&gt;This is not directly compatible with another account, therefore this is to be used as a guide to configure the elements in the logic apps.&lt;/em&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;definition&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;$schema&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;actions&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Respond_with_200&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;inputs&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;body&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;status&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;@{body(&amp;#39;Update_DNS_Entries&amp;#39;)?[&amp;#39;properties&amp;#39;]?[&amp;#39;provisioningState&amp;#39;]}&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;success&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;headers&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Content-Type&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;application/json; charset=utf-8&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;statusCode&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;200&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;kind&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Http&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;runAfter&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Update_DNS_Entries&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Succeeded&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Response&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Update_DNS_Entries&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;inputs&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;body&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;properties&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mode&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Incremental&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;template&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;$schema&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;contentVersion&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;1.0.0.0&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;parameters&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;destination_ip&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;defaultValue&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;@{triggerBody()?[&amp;#39;ip&amp;#39;]}&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;String&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;dnszones_name&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;defaultValue&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;ukr.lk&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;String&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;resources&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;apiVersion&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;2018-05-01&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;[concat(parameters(&amp;#39;dnszones_name&amp;#39;), &amp;#39;/home&amp;#39;)]&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;properties&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;ARecords&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;ipv4Address&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;[parameters(&amp;#39;destination_ip&amp;#39;)]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;TTL&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;600&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;targetResource&amp;#34;&lt;/span&gt;: {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Microsoft.Network/dnszones/A&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;apiVersion&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;2018-05-01&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;[concat(parameters(&amp;#39;dnszones_name&amp;#39;), &amp;#39;/*.home&amp;#39;)]&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;properties&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;ARecords&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;ipv4Address&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;[parameters(&amp;#39;destination_ip&amp;#39;)]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;TTL&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;600&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;targetResource&amp;#34;&lt;/span&gt;: {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Microsoft.Network/dnszones/A&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;variables&amp;#34;&lt;/span&gt;: {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;host&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;connection&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;@parameters(&amp;#39;$connections&amp;#39;)[&amp;#39;arm&amp;#39;][&amp;#39;connectionId&amp;#39;]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;method&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;put&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;path&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;/subscriptions/@{encodeURIComponent(&amp;#39;&amp;lt;sub_id&amp;gt;&amp;#39;)}/resourcegroups/@{encodeURIComponent(&amp;#39;ukr-rg-person-dns-eastasia&amp;#39;)}/providers/Microsoft.Resources/deployments/@{encodeURIComponent(&amp;#39;update_ip&amp;#39;)}&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;queries&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;wait&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;x-ms-api-version&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;2016-06-01&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;runAfter&amp;#34;&lt;/span&gt;: {},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;ApiConnection&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;contentVersion&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;1.0.0.0&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;outputs&amp;#34;&lt;/span&gt;: {},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;parameters&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;$connections&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;defaultValue&amp;#34;&lt;/span&gt;: {},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Object&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;triggers&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;manual&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;inputs&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;schema&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;properties&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;ip&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;string&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;object&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;kind&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Http&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Request&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;parameters&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;$connections&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;arm&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;connectionId&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;/subscriptions/&amp;lt;sub_id&amp;gt;/resourceGroups/ukr-rg-person-dns-eastasia/providers/Microsoft.Web/connections/arm&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;connectionName&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;arm&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;/subscriptions/&amp;lt;sub_id&amp;gt;/providers/Microsoft.Web/locations/eastasia/managedApis/arm&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Important lines to keep note (update based on your requirement),&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Line Number 38&lt;/em&gt; - The Name of your DNS Zone as in the domain name.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Line Number 45 &amp;amp; 59&lt;/em&gt; - The DNS entry path, in this use-case the A record is updated to the &lt;code&gt;home&lt;/code&gt; subdomain.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="part-3---updating-records-using-cron"&gt;&lt;strong&gt;Part 3&lt;/strong&gt; - Updating records using cron.&lt;/h2&gt;
&lt;p&gt;With my router having no custom dynamic IP options, the task was on a Raspberry PI. This was fairly simple, I whipped up a bash script and then added it on to crontab.&lt;/p&gt;
&lt;p&gt;Given below is the following script, please do change the webhook URL with your own.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;HIST_FILE&lt;span style="color:#f92672"&gt;=&lt;/span&gt;/tmp/dyn_ip_cur
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;WEB_HOOK&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;lt;enter webhook url&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Create Previous IP File if not present&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt; ! -f &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$HIST_FILE&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;]&lt;/span&gt;; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;The file &lt;/span&gt;$HIST_FILE&lt;span style="color:#e6db74"&gt; does not exist. Creating!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;0.0.0.0&amp;#34;&lt;/span&gt; &amp;gt; $HIST_FILE
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Fetch Previous IP From File&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PRV_IP&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;$(&lt;/span&gt;cat $HIST_FILE&lt;span style="color:#66d9ef"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Get Current IP&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CUR_IP&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;$(&lt;/span&gt;curl https://ip.42.pl/raw&lt;span style="color:#66d9ef"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Update Current IP to file&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;echo &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$CUR_IP&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &amp;gt; $HIST_FILE
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;echo &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$PRV_IP&lt;span style="color:#e6db74"&gt; -&amp;gt; &lt;/span&gt;$CUR_IP&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt; $CUR_IP !&lt;span style="color:#f92672"&gt;=&lt;/span&gt; $PRV_IP &lt;span style="color:#f92672"&gt;]&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;IP has updated to &lt;/span&gt;$CUR_IP&lt;span style="color:#e6db74"&gt; , updating on Azure&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; curl -L -X POST &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$WEB_HOOK&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -H &lt;span style="color:#e6db74"&gt;&amp;#39;Content-Type: application/json&amp;#39;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --data-raw &lt;span style="color:#e6db74"&gt;&amp;#34;{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; \&amp;#34;ip\&amp;#34; : \&amp;#34;&lt;/span&gt;$CUR_IP&lt;span style="color:#e6db74"&gt;\&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; }&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and in the crontab&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-cron" data-lang="cron"&gt;*/5 * * * * /root/azuredns/az.sh &amp;gt;/dev/null 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="show-me-the-money"&gt;Show Me The Money!&lt;/h2&gt;
&lt;p&gt;I got to emphasize, that this will depend on your usage &amp;amp; traffic. For my modest single user usage and not so pop wesbite I get around with $0.50 a month, which I think is pretty great!&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-3"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/azure-dyn-dns/az_dyn_moni_hu_e917d7b5262f848c.webp" width="1000" height="688" class="summary-image" alt="Azure DNS Zones Screenshot"&gt;
	
 &lt;figcaption&gt;Image 3: Azure DNS Zones Screenshot&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Azure is great, in this case Logic Apps. I was able to archive all my functional and non-functional requirements! Hope this was helpful and I was able to nudge someone in the correct direction.&lt;/p&gt;</description></item><item><title>Getting back into cycling</title><link>https://ukr.lk/posts/the-joy-of-riding-my-bike/</link><pubDate>Sun, 14 Jun 2020 19:25:24 +0000</pubDate><guid>https://ukr.lk/posts/the-joy-of-riding-my-bike/</guid><description>&lt;p&gt;Life during the lock-down is hard, It&amp;rsquo;s harder for the unfortunate who lost their jobs and is unable to work from home. I&amp;rsquo;m one of the lucky ones who&amp;rsquo;s able to work from home and continue on like nothing happen.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Still that doesn&amp;rsquo;t make it easy for me&lt;/strong&gt;, the monotonous workflow is broken. What was desensitized is now apparent. I needed some sort of escape, and for me that was cycling. I&amp;rsquo;ve been known to pace around a lot and being unable to stay in one place. Cycling is that but with much more speed.&lt;/p&gt;
&lt;h2 id="the-seed"&gt;The seed&lt;/h2&gt;
&lt;p&gt;I started out on my dad&amp;rsquo;s old &lt;a href="http://www.lumala.lk/"&gt;Lumala&lt;/a&gt; Sports bike which was original ridden by mum during her school days. Dad had re-painted it black and made it look very sleek. It&amp;rsquo;s my dad&amp;rsquo;s sole means of transportation around Battaramulla(City in Colombo) where I live.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/the-joy-of-riding-my-bike/IMG_20200430_162117_hu_1aeb50a860ae3193.webp" width="1000" height="1333" class="summary-image" alt="My cousin Kevin&amp;rsquo;s bike and the old Lumala"&gt;
	
 &lt;figcaption&gt;Image 1: My cousin Kevin&amp;rsquo;s bike and the old Lumala&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s creeky and has only front-breaks and makes really unpleasant sounds when going up hills. it had no-frills and I loved it. Kevin and I frequent the water tank near the temple to feed bread to the tortoise and fish there. Also after workday stress I circle the familiar roads in Battaramulla by myself to end the day off,&lt;/p&gt;
&lt;h2 id="buying-a-new-bike"&gt;Buying a new bike&lt;/h2&gt;
&lt;p&gt;Dad was not liking that his bike keeps disappearing. He demanded I get a new bike, and that&amp;rsquo;s what I did.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-2"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/the-joy-of-riding-my-bike/IMG_20200614_100545_hu_6111960d2d74cf61.webp" width="1000" height="750" class="summary-image" alt="The New Bike"&gt;
	
 &lt;figcaption&gt;Image 2: The New Bike&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Yes! new bike, the last time I owned a bicycle was when during school days. It was one of the common cheap mountain bikes with fancy decals and shocks. This time I did some research and bought a &lt;a href="https://www.suriyage.com/product.php?id=22"&gt;Ribow Hardtail 26&lt;/a&gt;, overkill? Maybe not as I really do plan to use the heck out of it.&lt;/p&gt;
&lt;p&gt;Also what contributed was seeing a blog by one of my former bosses at WSO2 write about her &lt;a href="http://cyclistories.blogspot.com/"&gt;cycling stories in Sri Lanka&lt;/a&gt;, looks like a lot of fun!&lt;/p&gt;
&lt;h2 id="riding-on-the-street"&gt;Riding on the Street&lt;/h2&gt;
&lt;p&gt;It rides like a dream I end up cycling around Battaramulla but I needed to head out of the familiar paths to have an adventure.&lt;/p&gt;
&lt;p&gt;It was apparent that I needed to get on the road, as I have slight fear of traffic and driving (I still don&amp;rsquo;t own a drivers licence). It was less scary than driving an automobile as I have confidence and know the limits of it&amp;rsquo;s maneuverability.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-3"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/the-joy-of-riding-my-bike/cycling_route_1_hu_6bb0cf4c6f8eb3d4.webp" width="1000" height="1034" class="summary-image" alt="First time on the road recorded on my P30Pro with GPS Logger"&gt;
	
 &lt;figcaption&gt;Image 3: First time on the road recorded on my P30Pro with GPS Logger&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;The first time was okay, I just went around Battaramulla and It was okay. It was all left turns and was non-eventful and invoked memories of me cycling in the road during school days going for tuition classes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Yesterday Morning (13/06/2020 Saturday)&lt;/strong&gt; I woke up with no plans and decided just to go on a proper cycling route. My waypoints on Google Maps were&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Start from &lt;a href="https://goo.gl/maps/PnRvrQmNYSGFrDcu5"&gt;Parliament Grounds Car Park&lt;/a&gt;..&lt;/li&gt;
&lt;li&gt;Go pass &lt;a href="https://goo.gl/maps/1ZPvhRLmtsP5zLgR6"&gt;Beddagana Wetland Park&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Go pass &lt;a href="https://goo.gl/maps/2eJWbtFWkpPobRYg8"&gt;Spinner Cafe&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Come back to the start.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I strapped my phone on the bike and fixed my flashy red tail light. I wasn&amp;rsquo;t feeling any anxiety. Just did it. Note: I don&amp;rsquo;t recommend this specific route as &lt;strong&gt;Google Maps In Sri Lanka doesn&amp;rsquo;t give cycling routes and this car route had some steep climbs.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-4"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/the-joy-of-riding-my-bike/cycling_route_2_hu_3aac35fe4b633932.webp" width="1000" height="1034" class="summary-image" alt="Woo! Look ma!"&gt;
	
 &lt;figcaption&gt;Image 4: Woo! Look ma!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I really enjoyed that round, going pass the temples at dawn and seeing the sunlight on the buildings high up while the roads were dim. I didn&amp;rsquo;t stop as most of the locations were closed and I didn&amp;rsquo;t bring my bike lock.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-5"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/the-joy-of-riding-my-bike/1_4-003_hu_3f50122e99288202.webp" width="1000" height="696" class="summary-image" alt="Just like Riding a Bike"&gt;
	
 &lt;figcaption&gt;Image 5: Just like Riding a Bike&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;There is something so free of feeling the road through the handlebars and swiftly navigating through small roads. I intend to keep it up and go on more cycling stories and take more pictures while at it!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;So do expect more cycling stories content on the site!&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>All Hail The JAM Stack!</title><link>https://ukr.lk/posts/all-hail-the-jam-stack/</link><pubDate>Mon, 08 Jun 2020 14:33:40 +0000</pubDate><guid>https://ukr.lk/posts/all-hail-the-jam-stack/</guid><description>&lt;p&gt;I was having troubles with my website. I got it settled up just to be a landing page. A website with a high bounce rate and low retention yikes!&lt;/p&gt;
&lt;p&gt;With leaving social media, I needed a new home to settle down my thoughts and have all my creations in one place instead of relying on other sites. Time to make the web personal again!


&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/all-hail-the-jam-stack/site_june_2020_c_hu_573a3310f157cc42.webp" width="1000" height="846" class="summary-image" alt="What it looks like - June 2020"&gt;
	
 &lt;figcaption&gt;Image 1: What it looks like - June 2020&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 id="whats-a-stack"&gt;What&amp;rsquo;s a stack?&lt;/h2&gt;
&lt;p&gt;A stack is simply the selection of software that you use to run an application. My first website ran on &lt;strong&gt;LAMP&lt;/strong&gt; Which was &lt;em&gt;Linux, Apache, Mysql and PHP&lt;/em&gt;. It wasn&amp;rsquo;t cool to have a /static website those days.&lt;/p&gt;
&lt;h2 id="then-whats-with-the-jam"&gt;Then What&amp;rsquo;s with the JAM?&lt;/h2&gt;
&lt;p&gt;Gone are the days of bulky server bootstrapping to get a simple website off the ground. JAM stack made it simple, it stands for,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;J&lt;/strong&gt;avascript.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A&lt;/strong&gt;PIs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;M&lt;/strong&gt;arkup.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The JAM stack is not really about the technologies used as some even totally drop the J from the stack. But it&amp;rsquo;s a way to approach building websites.&lt;/p&gt;
&lt;p&gt;Instead of having bulky databases and web-servers, sites are to be pre-rendered using the APIs and Markup.&lt;/p&gt;
&lt;center&gt;
 &lt;b&gt;I'm not going to regurgitate on the JAM Stack,&lt;br/&gt;read more on &lt;a href="https://jamstack.org/"&gt;jamstack.org&lt;/a&gt;&lt;/b&gt;
&lt;/center&gt;
&lt;h2 id="so-whats-my-jam-stack--why"&gt;So what&amp;rsquo;s my JAM Stack &amp;amp; Why?&lt;/h2&gt;
&lt;p&gt;My old website ran on &lt;a href="https://gohugo.io/"&gt;Hugo&lt;/a&gt; which was technically JAM, but I never filled it with content as I was just lazy to read the docs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Javscript:&lt;/strong&gt; This time I opted to use &lt;a href="https://nextjs.org/"&gt;Next.js&lt;/a&gt; and wrote my own CMS and rendered the UI with the &lt;a href="https://bulma.io/"&gt;Bulma&lt;/a&gt; CSS framework.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;APIs:&lt;/strong&gt; As said before I use my own custom one file Typescript CMS that reads off files. I call my &lt;em&gt;API&lt;/em&gt; the &lt;em&gt;&lt;strong&gt;_grail&lt;/strong&gt;&lt;/em&gt; which has all the data to generate this blog.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;_grail
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── categories
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── fintech.md
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── life.md
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── projects.md
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── web-dev.md
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── microblog
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── 2020-06-07T14:50:49+0000.md
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── 2020-06-07T15:21:14+00:00.md
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── pages
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── page_about.md
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── page_contact.md
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── page_home.md
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└── posts
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ├── 2019-06-08_All-Hail-The-JAM-Stack.md
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; └── 2020-05-08_Putting-the-past-on-disk-a077e62019eb.md
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; directories, &lt;span style="color:#ae81ff"&gt;24&lt;/span&gt; files
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Markup:&lt;/strong&gt; Good old markup with frontmatter to annotate metadata for each of the markdown posts&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-md" data-lang="md"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;slug: &amp;#34;1591541449&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;date: &amp;#34;2020-06-07T14:50:49+0000&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Hello World! It&amp;#39;s my lonely &lt;span style="font-style:italic"&gt;*micro-blog*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="current-workflow"&gt;Current Workflow&lt;/h2&gt;
&lt;p&gt;Current workflow requires me to write markdown on my text-editor and push it to a private github repository and afterwards it&amp;rsquo;s deployed instantly(Thanks to &lt;a href="https://www.netlify.com/"&gt;Netlify&lt;/a&gt;), &lt;strong&gt;but there are a couple of pain-points&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Quickly generate Content Templates&lt;/em&gt; - Currently I copy and old post markdown file and edit it, need some CLI.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Static file management&lt;/em&gt; - There is none, I currently just convert the images using IM and dump the images into the /static directories.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s not the best, I have to do my own styling and content structure. This allows me total control over the site and be able to expand it, which I will certainly do. Thanks for hanging on folks.&lt;/p&gt;</description></item><item><title>Putting the past on disk</title><link>https://ukr.lk/posts/putting-the-past-on-disk/</link><pubDate>Fri, 08 May 2020 19:25:24 +0000</pubDate><guid>https://ukr.lk/posts/putting-the-past-on-disk/</guid><description>&lt;p&gt;It was one of those nights, music blurring into noise and boredom kicks in. Random memories flood; in need of a distraction. One of the things I’ve regretted is throwing data away. Not any garbage files, but data with sentimental values.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Growing up with a computer from a young age, most of my fond memories are encoded in bits.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Being always on the lookout for a clean break. I often just deleted off my history, internet and physical. especially during school days.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/putting-the-past-on-disk/1__dRUA__VBJ2dR1bnVUNMeXSA_hu_50e91f9ed08df3e3.webp" width="1000" height="721" class="summary-image" alt="Scanner Collage of random things"&gt;
	
 &lt;figcaption&gt;Image 1: Scanner Collage of random things&lt;/figcaption&gt;
&lt;/figure&gt;

Back to that night, I wanted to find myself on the old-web. With careful google advance search queries with specific references, I managed to dig some of the old blogs. Lightheaded I scrolled through these blogs trying to save everything I can. Memories left recessed within, resurfaced with an old but familiar bad taste in my mouth.&lt;/p&gt;
&lt;h3 id="dusty-photoalbums"&gt;Dusty photo albums&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Another day&lt;/em&gt;. With the work from home grind during the COVID-19 pandemic, I step out of my room for a breather. I see outside, mum is rummaging through a box of old photo albums. I join her for a little roller-coster ride of the days past.&lt;/p&gt;
&lt;p&gt;I haven’t seen most of these photos. Many of them are of me doing various things with some occasional nudes sprinkled in(why?). &lt;strong&gt;With my recent encounter with my teenage blogs and the strong feeling of “need-for-archiving”,&lt;/strong&gt; I ask my mum to take the photos out of the albums to get scanned.&lt;/p&gt;
&lt;p&gt;Physical hard-copies are the best form for these pictures to survive, but remember “Backups are important”!&lt;/p&gt;
&lt;h3 id="the-scanningproject"&gt;The scanning project&lt;/h3&gt;
&lt;p&gt;I return to my room to pick work back up, But I was giddy to get this project started. During breaks between work calls, Googling was done; on to figure the best way to get these photos down to disk. I set a mental mission for this project,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Get all the photos backed up as easily as possible at the best quality. Make them easily accessible.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;With that in mind, I first needed a Scanner. I don’t have a scanner myself but my uncle has many of them. He’s the sort of cool uncle who migrated to digital early on. He used to digitize a lot of images, but the backup mediums were poor, He tired.&lt;/p&gt;
&lt;h4 id="the-scanner"&gt;The Scanner&lt;/h4&gt;
&lt;p&gt;I waited till my uncle gets home from work. Bit of small talk and I asked for a scanner. Target acquired! &lt;strong&gt;The Canon CanoScan LIDE 100&lt;/strong&gt; is mine now! It’s a portable flatbed scanner from 2004. Sleek and bus-powered through USB. My iMac picked it up with zero monkeying around. Moment of appreciation for plug-and-play.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-2"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/putting-the-past-on-disk/1__Nvh3TEOWrIk1mYLzEyyCAQ_hu_6f067bfeaba1efaa.webp" width="1000" height="750" class="summary-image" alt="The Canon CanoScan LIDE 100 with the rest of my setup"&gt;
	
 &lt;figcaption&gt;Image 2: The Canon CanoScan LIDE 100 with the rest of my setup&lt;/figcaption&gt;
&lt;/figure&gt;

It’s has a &lt;a href="https://www.twain.org/"&gt;&lt;strong&gt;TWAIN&lt;/strong&gt;&lt;/a&gt;-compatible driver, so now I need &lt;a href="http://www.sane-project.org/"&gt;&lt;strong&gt;SANE&lt;/strong&gt;&lt;/a&gt;. &lt;em&gt;If you’re scratching your head right about now and ready to “Search Google for” now please refrain.&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;TWAIN&lt;/strong&gt; is an API for communication between software and digital imaging cameras or scanners.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SANE&lt;/strong&gt; stands for “Scanner Access Now Easy” what a lovely acronym! It’s a standardised interface to access image scanners.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;“Well Kaveen, why use SANE when you have TWAIN?”&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;The&lt;/em&gt; &lt;a href="http://www.sane-project.org/"&gt;&lt;em&gt;SANE project&lt;/em&gt;&lt;/a&gt; &lt;em&gt;home-page explains it best&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“In summary, if TWAIN had been just a little better designed, there would have been no reason for &lt;em&gt;SANE&lt;/em&gt; to exist, but things being the way they are, TWAIN simply isn’t &lt;em&gt;SANE&lt;/em&gt;.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Tech tangent aside&lt;/em&gt;&lt;/strong&gt;, with SANE I can quickly get a TIFF out of the scanner without having to cry interacting with GUIs.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;scanimage -p &lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --mode color &lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --format tiff &lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --resolution &lt;span style="color:#ae81ff"&gt;600&lt;/span&gt; &amp;gt; &lt;span style="color:#ae81ff"&gt;\`&lt;/span&gt;date +%s&lt;span style="color:#ae81ff"&gt;\`&lt;/span&gt;.tiff
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Some might say that is INSANE. The above configuration is to scan at 600 DPI in colour.&lt;/p&gt;
&lt;h4 id="scanning-thephotos"&gt;Scanning The Photos&lt;/h4&gt;
&lt;p&gt;Moving along. Armed with SANE now, I must decide how I can get the most of my time. I have a couple of options regarding how to take on the scanning.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;⚠️ &lt;em&gt;Important note: I don’t want to do the manual labour of cropping pictures, I’ll waste my time automating it instead.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;**Scan a single image at a time **— Too slow but I can quickly crop using a set coordinates.&lt;/li&gt;
&lt;li&gt;**Setup a scan layout with multiple images **— Fast and I can establish multiple crop areas using coordinates, but can’t accommodate different photo sizes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;auto-mask and identify multiple images&lt;/strong&gt; — &lt;em&gt;AUTO-MAGICK&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;

&lt;figure id="image-3"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/putting-the-past-on-disk/1__5RYRkBdWWvTgN__FwkpMrbg_hu_bc6dc0b94d78b47a.webp" width="1000" height="1395" class="summary-image" alt="The Scanning Layout Selected, Photos are aligned with the edges of the scanner. but precision is not required as auto-masking will be used."&gt;
	
 &lt;figcaption&gt;Image 3: The Scanning Layout Selected, Photos are aligned with the edges of the scanner. but precision is not required as auto-masking will be used.&lt;/figcaption&gt;
&lt;/figure&gt;

I went the auto-magick route, that’s no misspelling but let’s revisit that part later in this account.&lt;/p&gt;
&lt;p&gt;I created myself a little bash script to keep continually scanning. It will simply let me scan images and save each of the TIFF files with the current timestamp as the name.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; true; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; scanimage -p &lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --mode color &lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --format tiff &lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --resolution &lt;span style="color:#ae81ff"&gt;600&lt;/span&gt; &amp;gt; &lt;span style="color:#ae81ff"&gt;\`&lt;/span&gt;date +%s&lt;span style="color:#ae81ff"&gt;\`&lt;/span&gt;.tiff
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;echo &lt;span style="color:#e6db74"&gt;&amp;#34;Press Any Key but ESC to continue scanning&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; read -r -n1 key 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\[\[&lt;/span&gt; $key &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;$&amp;#39;\\e&amp;#39;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\]\]&lt;/span&gt;; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; break; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;fi&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="splitting-the-scanned-tifffiles"&gt;Splitting The Scanned TIFF files&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://imagemagick.org/index.php"&gt;“Image Magick”&lt;/a&gt; that’s what saved this project. &lt;em&gt;It’s mind-blowing to know that Image Magick project had its initial release almost 30 years ago!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;During my initial research for this project, I came across this script called &lt;a href="http://www.fmwconcepts.com/imagemagick/multicrop/index.php"&gt;“multicrop” by Fred Weinhaus&lt;/a&gt;. &lt;em&gt;He also has some amazing scripts utilising IM(Image Magick).&lt;/em&gt; &lt;strong&gt;With multicrop, it’s just,&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;./multicrop -f &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -u &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -d &lt;span style="color:#ae81ff"&gt;300&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -p &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -b &lt;span style="color:#e6db74"&gt;&amp;#39;#e9ecea&amp;#39;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; in.tiff out.tiff
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Just by running this bash script it automatically masks out the blank spaces and spits out multiple output tiff files! Multicrop was a godsend, but&lt;/p&gt;
&lt;p&gt;☹️ &lt;strong&gt;&lt;em&gt;It didn’t work out of the box under my circumstance. The results were all over the place.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h4 id="why-wasnt-multicrop-working-forme"&gt;Why wasn’t multicrop working for me?&lt;/h4&gt;
&lt;p&gt;After scratching my head for some time, It was the scans! &lt;strong&gt;My scanner doesn’t spit out a uniform background. The backing of the scanner has deformed in the corners which appear on the scans&lt;/strong&gt;; to the script, these look like part of an image.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;How did I catch this?&lt;/em&gt;&lt;/strong&gt; The multicrop script has &lt;em&gt;`-m`&lt;/em&gt; switch that allows you to save the mask for debugging purposes.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;./multicrop -f &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -u &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -d &lt;span style="color:#ae81ff"&gt;300&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -p &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -b &lt;span style="color:#e6db74"&gt;&amp;#39;#e9ecea&amp;#39;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -m save &lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; in.tiff out.tiff
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;

&lt;figure id="image-4"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/putting-the-past-on-disk/1__r2y5Jt9iuN83uhbXVag__iA_hu_59070d366ebc0b9e.webp" width="1000" height="697" class="summary-image" alt="The left image shows the raw mask of the scanner and the right is after being trimmed via IM."&gt;
	
 &lt;figcaption&gt;Image 4: The left image shows the raw mask of the scanner and the right is after being trimmed via IM.&lt;/figcaption&gt;
&lt;/figure&gt;

This should be a fairly trivial fix as I can lose some of the pixels on the edges and get rid of the problem. &lt;strong&gt;IM back to the rescue!&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;magick convert in.tiff &lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -shave 15x45 &lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; in&lt;span style="color:#ae81ff"&gt;\_&lt;/span&gt;shaved.tiff
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you can see the result is apparent, &lt;strong&gt;The script is now able to separate scans with a negligible amount of failures.&lt;/strong&gt; Now we’re full steam ahead on getting all these scanned images processed!&lt;/p&gt;
&lt;h4 id="end-of-the-line-writing-a-bash-script-to-bulk-process-thescans"&gt;End of the line, writing a bash-script to bulk process the scans&lt;/h4&gt;
&lt;p&gt;Crisis averted, To wrap up, a folder structure was established to keep images in albums for easy organisation. This will help in the last part which is syncing the images on the cloud provider.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;⚠️ Warning: Please excuse the crudeness of these bash scripts&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;imagePath&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;/Users/kaveenr/ImageScanning&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;processIt &lt;span style="color:#f92672"&gt;()&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;Shaving edges of &lt;/span&gt;$1&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tmpFile&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;/tmp/sane\_scan\_&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;$(&lt;/span&gt;date +%s&lt;span style="color:#66d9ef"&gt;)&lt;/span&gt;&lt;span style="color:#e6db74"&gt;.tiff&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; magick convert &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$1&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; -shave 15x45 $tmpFile 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ./multicrop -f &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -u &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -d &lt;span style="color:#ae81ff"&gt;300&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -p &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -b &lt;span style="color:#e6db74"&gt;&amp;#39;#e9ecea&amp;#39;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $tmpFile &lt;span style="color:#e6db74"&gt;&amp;#34;./&lt;/span&gt;$2&lt;span style="color:#e6db74"&gt;/&lt;/span&gt;$3&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; rm $tmpFile 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;Processed Under &lt;/span&gt;$outPath&lt;span style="color:#e6db74"&gt;/&lt;/span&gt;$fileName&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;find $imagePath -name &lt;span style="color:#e6db74"&gt;&amp;#34;\*.tiff&amp;#34;&lt;/span&gt; | &lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; read line; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; fileName&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;$(&lt;/span&gt;basename &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$line&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;)&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; fileName&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;fileName// /&lt;span style="color:#ae81ff"&gt;\_&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; fileDir&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;$(&lt;/span&gt;dirname &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$line&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;)&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; outPath&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;out&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;fileDir#$imagePath&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; outPath&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;outPath// /&lt;span style="color:#ae81ff"&gt;\_&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mkdir -p &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$outPath&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Check Path &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; checkPath&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;./&lt;/span&gt;$outPath&lt;span style="color:#e6db74"&gt;/&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;fileName%.tiff&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;-\*.tiff&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;checking path &lt;/span&gt;$checkPath&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; ls $checkPath 1&amp;gt; /dev/null 2&amp;gt;&amp;amp;1; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;files do exist for &amp;#39;&lt;/span&gt;$line&lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; processIt &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$line&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$outPath&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$fileName&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;fi&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This first script will take the scanned images; do the aforementioned trimming and run it through multicrop.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-5"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/putting-the-past-on-disk/1__o37cCeIN2iuKyD__UPP06cA_hu_ba44a8879b4a1e7a.webp" width="1000" height="659" class="summary-image" alt="Woo!"&gt;
	
 &lt;figcaption&gt;Image 5: Woo!&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;strong&gt;🥳 Profit! Now you have an output folder with albums and splitter tiff files.&lt;/strong&gt;&lt;/p&gt;
&lt;h4 id="the-easily-accessible-part-of-themission"&gt;The easily accessible part of the mission&lt;/h4&gt;
&lt;p&gt;Hold on, the mission of this project had “&lt;strong&gt;&lt;em&gt;Make the albums easily accessible.”&lt;/em&gt;&lt;/strong&gt;. At this point, I’ve already synced these photos to a cloud drive and another local-offline backup.&lt;/p&gt;
&lt;p&gt;As for the ease of access, I decided to add the images to my cloud photos manager Google Photos. Scripting time!&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;imagePath&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;/Users/kaveenr/Projects/sane-scan-photo/out&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ls $imagePath | &lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; read album; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; albumTitle&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;album//&lt;span style="color:#ae81ff"&gt;\_&lt;/span&gt;/ &lt;span style="color:#e6db74"&gt;}&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; albumTitle&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;albumTitle%%(&lt;span style="color:#ae81ff"&gt;\*&lt;/span&gt;)&lt;span style="color:#e6db74"&gt;}&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; albumTitle&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;albumTitle%% &lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;echo &lt;span style="color:#e6db74"&gt;&amp;#34;Syncing &lt;/span&gt;$albumTitle&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; rclone sync $imagePath/$album &lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Photos:album/&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$albumTitle&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; -P 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Apart from some album renaming the heavy lifting is done by &lt;a href="https://rclone.org/"&gt;Rclone&lt;/a&gt; and it’s &lt;a href="https://rclone.org/googlephotos/"&gt;Google Photos&lt;/a&gt; backend.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-6"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/putting-the-past-on-disk/1__CuZJI__Yh6FvLoWI4Ykrohg_hu_4b90bd50bbba7234.webp" width="1000" height="659" class="summary-image" alt="The End. Memories On Google Photos"&gt;
	
 &lt;figcaption&gt;Image 6: The End. Memories On Google Photos&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;strong&gt;🎉 Done! Now I’m able to browse photos easily on Google Photos and share it with my parents!&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="takeaways"&gt;Takeaways&lt;/h3&gt;
&lt;p&gt;It feels great to write something again. Apart from feelings and sorts. In short, the following points summarize this project in total.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-7"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/putting-the-past-on-disk/1__GbcHalnLeuYWsnMbKhBccA_hu_82b7df68aefb36c9.webp" width="1000" height="782" class="summary-image" alt="Happiness, Me feeding “Rollo” the cat cake on my 7th birthday (2004)"&gt;
	
 &lt;figcaption&gt;Image 7: Happiness, Me feeding “Rollo” the cat cake on my 7th birthday (2004)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Back your shiz up — For images as said before physical is the way to go, but always have a secondary soft-copy.&lt;/li&gt;
&lt;li&gt;Think twice before you delete anything, you might regret later.&lt;/li&gt;
&lt;li&gt;Image Magick is amazing. I’ve been converted. I actually manipulated all of the images for this post using IM.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Personally, this was my first entry into bash-scripting as I often use Python for most automation tasks. And with tools like IM, it’s unbelievably easy to write image related scripts in bash. &lt;em&gt;Next is ffmpeg….&lt;/em&gt;&lt;/p&gt;
&lt;h3 id="appendices"&gt;Appendices&lt;/h3&gt;
&lt;p&gt;Heh, I have more if you’re interested. Some stuff that is too boring to cram into the main section&lt;/p&gt;
&lt;h4 id="multicrop-parameter-notes"&gt;Multicrop parameter Notes&lt;/h4&gt;
&lt;p&gt;Configuration Notes:-b ‘#e9ecea’ — Background Color to be masked out&lt;br&gt;
-f 20 — fuzzy match background threshold (for non-uniform backgrounds)&lt;br&gt;
-d 300 — discard identified regions if they are smaller than 300 pixels&lt;/p&gt;
&lt;h4 id="adding-exif-data--compressing-toheic"&gt;Adding EXIF Data &amp;amp; Compressing to HEIC&lt;/h4&gt;
&lt;p&gt;I created an EXIF data script that will extract the date or year from the folder and embed it into the image. I decided to compress the images to HEIC which is much better than JPEG compression.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;imagePath&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;/Users/kaveenr/Projects/sane-scan-photo/out&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;yearRegex&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;\\((\[0-9\]{4})\\)&amp;#39;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dateRegex&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;\\((\[0-9\]{4})\\:(\[0-9\]{2})\\:(\[0-9\]{2})\\)&amp;#39;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;targetFormat&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;heic&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ls $imagePath | &lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; read album; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; albumTitle&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;album//&lt;span style="color:#ae81ff"&gt;\_&lt;/span&gt;/ &lt;span style="color:#e6db74"&gt;}&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\[\[&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$albumTitle&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt;~ $yearRegex &lt;span style="color:#ae81ff"&gt;\]\]&lt;/span&gt;; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; guessYear&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;BASH&lt;span style="color:#ae81ff"&gt;\_&lt;/span&gt;REMATCH&lt;span style="color:#ae81ff"&gt;\[&lt;/span&gt;1&lt;span style="color:#ae81ff"&gt;\]&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;Found Year in title &lt;/span&gt;$guessYear&lt;span style="color:#e6db74"&gt;, Setting EXIF Data&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; exiftool -overwrite&lt;span style="color:#ae81ff"&gt;\_&lt;/span&gt;original &lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -xmp:dateTimeOriginal&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$guessYear&lt;span style="color:#e6db74"&gt;:1:1&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -r $imagePath/$album/ 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;fi&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\[\[&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$albumTitle&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt;~ $dateRegex &lt;span style="color:#ae81ff"&gt;\]\]&lt;/span&gt;; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; guessYear&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;BASH&lt;span style="color:#ae81ff"&gt;\_&lt;/span&gt;REMATCH&lt;span style="color:#ae81ff"&gt;\[&lt;/span&gt;1&lt;span style="color:#ae81ff"&gt;\]&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; guessMonth&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;BASH&lt;span style="color:#ae81ff"&gt;\_&lt;/span&gt;REMATCH&lt;span style="color:#ae81ff"&gt;\[&lt;/span&gt;2&lt;span style="color:#ae81ff"&gt;\]&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; guessDay&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;BASH&lt;span style="color:#ae81ff"&gt;\_&lt;/span&gt;REMATCH&lt;span style="color:#ae81ff"&gt;\[&lt;/span&gt;3&lt;span style="color:#ae81ff"&gt;\]&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;Found Date in title &lt;/span&gt;$guessYear&lt;span style="color:#e6db74"&gt;/&lt;/span&gt;$guessMonth&lt;span style="color:#e6db74"&gt;/&lt;/span&gt;$guessDay&lt;span style="color:#e6db74"&gt;, Setting EXIF Data&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; exiftool -overwrite&lt;span style="color:#ae81ff"&gt;\_&lt;/span&gt;original &lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -xmp:dateTimeOriginal&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$guessYear&lt;span style="color:#e6db74"&gt;:&lt;/span&gt;$guessMonth&lt;span style="color:#e6db74"&gt;:&lt;/span&gt;$guessDay&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\\&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -r $imagePath/$album/ 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;fi&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; ls $imagePath/$album/compressed 1&amp;gt; /dev/null 2&amp;gt;&amp;amp;1; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;Album &lt;/span&gt;$albumTitle&lt;span style="color:#e6db74"&gt; already compressed&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;Compressing &lt;/span&gt;$albumTitle&lt;span style="color:#e6db74"&gt; to &lt;/span&gt;$targetFormat&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt;cd $imagePath/$album ; magick mogrify -quality 100% -format $targetFormat &lt;span style="color:#ae81ff"&gt;\*&lt;/span&gt;.tiff&lt;span style="color:#f92672"&gt;)&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt;cd $imagePath/$album ; mkdir -p compressed; mv &lt;span style="color:#ae81ff"&gt;\*&lt;/span&gt;.$targetFormat compressed&lt;span style="color:#f92672"&gt;)&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;fi&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;Note: Ultimately these tags were not picked up by Google Photos for some reason I suspect it’s the HEIC format.&lt;/em&gt;&lt;/p&gt;
&lt;h4 id="q-how-many-photos-did-i-backup"&gt;Q: How many photos did I back up?&lt;/h4&gt;
&lt;p&gt;Not that much, 371&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ find ./out -name &lt;span style="color:#e6db74"&gt;&amp;#34;\*.tiff&amp;#34;&lt;/span&gt; | wc -l 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;371&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Financial APIs, pushing the boundaries of Identity</title><link>https://ukr.lk/posts/financial-apis-pushing-the-boundaries-of-identity/</link><pubDate>Sun, 29 Sep 2019 03:58:22 +0000</pubDate><guid>https://ukr.lk/posts/financial-apis-pushing-the-boundaries-of-identity/</guid><description>&lt;p&gt;Almost everyone will say &lt;strong&gt;“Publishing APIs are easy, Securing them is the hard part”&lt;/strong&gt;. Sentiment remains, in the realms of financial APIs. A wave of Financial APIs have hit the proverbial shores of the internet, and much deeper thought is required in terms of how &lt;a href="https://en.wikipedia.org/wiki/Identity_management"&gt;Identity and Access Management(IAM)&lt;/a&gt; is applied in this context.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/financial-apis-pushing-the-boundaries-of-identity/0__rFs4__x0CYN6HNpmj_hu_12e0257b58eece48.webp" width="1000" height="666" class="summary-image" alt="Photo by 小谢 on Unsplash"&gt;
	
 &lt;figcaption&gt;Image 1: Photo by &lt;a href="https://unsplash.com/@guogete?utm_source=medium&amp;amp;utm_medium=referral"&gt;小谢&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

Photo by &lt;a href="https://unsplash.com/@guogete?utm_source=medium&amp;amp;utm_medium=referral"&gt;小谢&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;With regulatory directive such as PSD2 which presents a framework to expose banking data and services to trusted parties; Identity plays a crucial role. &lt;em&gt;To learn more about Open Banking check out the article below&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://medium.com/gin-and-tonic/open-banking-and-psd2-simplified-6b34fce38a1a" title="https://medium.com/gin-and-tonic/open-banking-and-psd2-simplified-6b34fce38a1a"&gt;&lt;strong&gt;Open Banking and PSD2 simplified.&lt;/strong&gt;&lt;br&gt;
_The wave of Open Banking has hit the shore, is it a fad or a goldmine? only time will decide, I believe in the latter…_medium.com&lt;/a&gt;&lt;a href="https://medium.com/gin-and-tonic/open-banking-and-psd2-simplified-6b34fce38a1a"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In the domain of financial APIs questions such as listed below arise,&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;— How to ensure that only trusted parties will access these APIs?&lt;br&gt;
 — How to effectively authenticate users and get consent? &lt;br&gt;
— How to ensure that data is harnessed with customer consent?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;These questions are to be considered with a keen eye and implemented according to specification to safeguard the power of these APIs.&lt;/p&gt;
&lt;h3 id="the-beauty-of-modern-financial-apis"&gt;The beauty of modern financial APIs&lt;/h3&gt;
&lt;p&gt;Gone are the days of proprietary protocols, Open Banking ushered a new era of open design philosophy to industries adopting standards such as OpenAPI, OAuth, Open ID Connect.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;img src="https://ukr.lk/posts/financial-apis-pushing-the-boundaries-of-identity/1__cXlsLECOiHP0pwGD0R4Vzg.jpeg"&gt;
&lt;/figure&gt;

Following up PSD2, many countries and regulatory bodies were interested. In Australia is Consumer Data Right(CDR) fronted by Data61 who opened up the &lt;a href="https://github.com/ConsumerDataStandardsAustralia/standards"&gt;standards process on Github&lt;/a&gt; therefore whoever is interested in the standard is able to contribute.&lt;/p&gt;
&lt;p&gt;With growing interests in the space, OpenID foundation started a new &lt;a href="https://openid.net/wg/fapi/"&gt;workgroup&lt;/a&gt; back in 2017 drafting specifications suitable for financial APIs,&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;img src="https://ukr.lk/posts/financial-apis-pushing-the-boundaries-of-identity/1__IFes3rTB2v__2iPLjYFKlcg.jpeg"&gt;
&lt;/figure&gt;

The specifications by FAPI WG eventually became the backbone of modern financial APIs.&lt;/p&gt;
&lt;h3 id="is-open-banking-the-killer-application-for-identity"&gt;Is Open Banking the killer application for Identity?&lt;/h3&gt;
&lt;p&gt;Just like how VisiCalc or Lotus 1–2–3 became the &lt;a href="https://en.wikipedia.org/wiki/Killer_application"&gt;killer apps&lt;/a&gt; of the Apple II and IBM PC, respectively. Will financial APIs become the killer app for IAM?&lt;/p&gt;
&lt;p&gt;I’d love to claim this subtitle but it was posed in a panel during a recent Sibos conference. A debate took place on the core idea of how financial APIs are pushing the envelope of identity.&lt;/p&gt;
&lt;p&gt;Working in the integration domain this is quite apparent with commercial IAM products being updated to support FAPI grade security specifications.&lt;/p&gt;
&lt;p&gt;These specifications are to toughen the OAuth 2.0 authorization framework to tighten up sender, receiver and message security.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-2"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/financial-apis-pushing-the-boundaries-of-identity/1__NfV4JQoJ8A1__RQxveJNkeg_hu_e3615d62b38823ab.webp" width="1000" height="504" class="summary-image" alt="Excerpt from OpenID Foundation FAPI WG: June 2017 Update"&gt;
	
 &lt;figcaption&gt;Image 2: Excerpt from &lt;a href="https://www.slideshare.net/nat_sakimura/openid-foundation-fapi-wg-june-2017-update?ref=https://openid.net/wg/fapi/"&gt;OpenID Foundation FAPI WG: June 2017 Update&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

Excerpt from &lt;a href="https://www.slideshare.net/nat_sakimura/openid-foundation-fapi-wg-june-2017-update?ref=https://openid.net/wg/fapi/"&gt;OpenID Foundation FAPI WG: June 2017 Update&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The slide excerpt given above sums up what FAPI WG is trying to solve. IAM products are catching up to cater these specifications allowing usage in Open Banking scenarios.&lt;/p&gt;
&lt;p&gt;The EU’s approach is much more ambitious to make identity pan europian with eIDAS, implementation of eIDAS has become mandatory in the region in the Open Banking context. &lt;em&gt;To learn more about eIDAS check out the article below.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://medium.com/gin-and-tonic/eidas-solving-psd2s-identity-problems-c80ebc6c0a70" title="https://medium.com/gin-and-tonic/eidas-solving-psd2s-identity-problems-c80ebc6c0a70"&gt;&lt;strong&gt;eiDAS, solving PSD2’s identity problems.&lt;/strong&gt;&lt;br&gt;
_One of the biggest problems in Open Banking is identity. eIDAS is the saviour allowing a single method of trust to be…_medium.com&lt;/a&gt;&lt;a href="https://medium.com/gin-and-tonic/eidas-solving-psd2s-identity-problems-c80ebc6c0a70"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;With regulators from different countries coming into Open Banking &lt;strong&gt;it’s not so easy to dismiss the question &lt;em&gt;“Is Open Banking the killer application for Identity?”&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It’s an interesting time for Identity with new standards and specifications to cross borders from consumer singular scenarios to large scale financial API use cases. With adoption and time, these specifications might be adopted and evolved to be the norm in the future, giving a strong framework for high risk and low control scenarios.&lt;/p&gt;</description></item><item><title>Peek Into Upcoming Personal Data Protection Bill For Sri Lanka</title><link>https://ukr.lk/posts/peek-into-upcoming-personal-data-protection-bill-for-sri-lanka/</link><pubDate>Sun, 23 Jun 2019 14:30:03 +0000</pubDate><guid>https://ukr.lk/posts/peek-into-upcoming-personal-data-protection-bill-for-sri-lanka/</guid><description>&lt;p&gt;The &lt;a href="http://www.mdiit.gov.lk"&gt;Ministry of Digital Infrastructure and Information Technology (MDIIT)&lt;/a&gt; has recently published a framework for the proposed Data Protection Bill. With personal data being an important asset; especially in the digital age, MDTII has penned a &lt;a href="http://www.mdiit.gov.lk/index.php/en/mtdi-news/item/9-framework-for-the-proposed-personal-data-protection-act"&gt;framework document&lt;/a&gt; outlining the core stakeholders and key principles for personal data protection.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/peek-into-upcoming-personal-data-protection-bill-for-sri-lanka/0__YK39jt9YdwUHPvsu_hu_3365bc2f164916df.webp" width="1000" height="560" class="summary-image" alt="Photo by Taylor Vick on Unsplash"&gt;
	
 &lt;figcaption&gt;Image 1: Photo by &lt;a href="https://unsplash.com/@tvick?utm_source=medium&amp;amp;utm_medium=referral"&gt;Taylor Vick&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

Photo by &lt;a href="https://unsplash.com/@tvick?utm_source=medium&amp;amp;utm_medium=referral"&gt;Taylor Vick&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://parliament.lk/en/members-of-parliament/directory-of-members/viewMember/3143"&gt;Ajith P. Perera&lt;/a&gt; of Non-Cabinet Minister of MDIIT stated the importance of cybersecurity and data protection and how it’s paramount moving towards a digital economy.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;He further said that the IT sector is the country’s fourth largest foreign exchange earner and with the enactment of the new data protection and cyber security laws, it will become the country’s largest foreign exchange earners within the next 10 years.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;He also added that the Ease of Doing Business Index of the country will be increased with the improvement of country’s digital infrastructure facilities.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;(&lt;/em&gt; &lt;a href="http://www.dailynews.lk/line/ishara-mudugamuwa"&gt;&lt;em&gt;Ishara Mudugamuwa&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href="http://www.dailynews.lk"&gt;&lt;em&gt;Daily News&lt;/em&gt;&lt;/a&gt;&lt;em&gt;)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Tech-savvy data protection acts have been taking over and transforming the way data is procured and exposed. The drafting community of the framework made sure to take an example from regulations such as &lt;a href="https://eugdpr.org/"&gt;GDPR&lt;/a&gt; in the EU.&lt;/p&gt;
&lt;h3 id="understanding-the-nuts-and-bolts-of-the-framework"&gt;Understanding the nuts and bolts of the framework&lt;/h3&gt;
&lt;p&gt;At the current stage, a full framework is outlined for the proposed bill which identifies the main actors and principles. The main actors one should be aware of is the Data Subject-the person whose data is at stake, controller a body who is interested in the processing of data.&lt;/p&gt;
&lt;h4 id="main-stakeholders-in-the-framework"&gt;Main Stakeholders In The Framework&lt;/h4&gt;
&lt;p&gt;The following stakeholders play some of the main roles in the framework.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Data Subject&lt;/strong&gt; — Directly or indirectly identified or identifiable natural person, This is not limited to a name and can contain unique identification numbers, online identifier, location, etc.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Controller&lt;/strong&gt; — Legal person, authority or a body that collects data and engages in the processing of said data, through a processor with a clear purpose and consent. &lt;strong&gt;&lt;em&gt;“Consent” is freely given, specific, and unambiguous written declaration by the data subject.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Processor&lt;/strong&gt; — Legal person, authority or a body which processes data on behalf of a controller. A Processor shall be a separate entity from the controller which includes said entity not taking any part in the hierarchy of the controller. &lt;strong&gt;&lt;em&gt;“Processing”&lt;/em&gt;&lt;/strong&gt; &lt;strong&gt;&lt;em&gt;is an operation of personal data which is not limited to collection, storage, preservation, making available, consultation, logical operations, etc.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;**Authority **— Body that is appointed to register and govern controllers, In charge of certifying controllers and revoking in case of foul play is some of the tasks held by the authority.&lt;/p&gt;
&lt;h4 id="rights-of-data-subjects--consumers"&gt;Rights Of Data Subjects / Consumers&lt;/h4&gt;
&lt;p&gt;Data subjects such as you and I interact with certain bodies who are interested in processing data through processors. In Part 3 of the framework outlines the primary rights of data subjects.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Consent&lt;/strong&gt; — Subject has rights to withdraw consent of the processing of personal data from controllers, &lt;em&gt;“ For the Data Subject it shall be as easy to withdraw as to give consent”&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Right Of Access&lt;/strong&gt; — Subject is entitled to request from controllers whether their personal data is being processed and the purpose and legal basis for processing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rectification&lt;/strong&gt; — In the case, the data processed is inaccurate the data subject is able to correct any data with the controller.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Erasure&lt;/strong&gt; — Data subject is able to in written request the erasure of the data held by the controller to a certain extent.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="data-protection-principles"&gt;Data Protection Principles&lt;/h4&gt;
&lt;p&gt;Data protection principles are covered in part 2 of the framework outlines core values to be preserved in the handling of personal data.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Lawfulness in processing&lt;/strong&gt; — Personal data is processed in a lawful and transparent manner.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Purpose limitation&lt;/strong&gt; — Personal data collected is for an explicit and legitimate purpose and no further processing can take place outside the intended purpose. This has exceptions when it comes to archival and scientific and public interest.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Data Minimisation&lt;/strong&gt; — The data collected should be minimized to be adequate and relevant for the original reason.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Accuracy&lt;/strong&gt; — Controller should ensure the data is accurate and up to date.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Storage Limitation&lt;/strong&gt; — Personal data kept in a manner where identification of data subject may be kept for the period of time that is required for processing, otherwise data may be stored for archival reasons. &lt;em&gt;It’s unclear at the moment if archival data contain uniquely identifiable tags for data subjects.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;**Integrity and Confidentiality **— Personal data is processed ensuring appropriate security and protection against unlawful/unauthorized processing.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With acts such as this, Sri Lanka maybe ushering a new generation for technology that will allow safe and secure data processing and may pave the way for Open Data architecture for creating applications with consent like Open Banking. You can read the following to learn more about Open Banking and how it can transform financial technology.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://medium.com/gin-and-tonic/open-banking-and-psd2-simplified-6b34fce38a1a" title="https://medium.com/gin-and-tonic/open-banking-and-psd2-simplified-6b34fce38a1a"&gt;&lt;strong&gt;Open Banking and PSD2 simplified.&lt;/strong&gt;&lt;br&gt;
_The wave of Open Banking has hit the shore, is it a fad or a goldmine? only time will decide, I believe in the latter…_medium.com&lt;/a&gt;&lt;a href="https://medium.com/gin-and-tonic/open-banking-and-psd2-simplified-6b34fce38a1a"&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Understanding Idempotency in REST APIs</title><link>https://ukr.lk/posts/understanding-idempotency-in-rest-apis/</link><pubDate>Fri, 19 Apr 2019 16:19:32 +0000</pubDate><guid>https://ukr.lk/posts/understanding-idempotency-in-rest-apis/</guid><description>&lt;p&gt;Incorporating idempotency is an important part of building robust and predictable APIs. In basic terms, idempotence is a scenario where how many times the action may be performed but the outcome remains the same.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;for a basic example, take &lt;strong&gt;f(x) = x*x&lt;/strong&gt;, How many times you may call &lt;strong&gt;f(5)&lt;/strong&gt; it’s always going to be the same outcome &lt;strong&gt;25,&lt;/strong&gt; This request is idempotant.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/understanding-idempotency-in-rest-apis/0__X4yIOCkzzugyrGoA_hu_4d0e38a95a9d85.webp" width="1000" height="666" class="summary-image" alt="Photo by Jordan Harrison on Unsplash"&gt;
	
 &lt;figcaption&gt;Image 1: Photo by &lt;a href="https://unsplash.com/@aligns?utm_source=medium&amp;amp;utm_medium=referral"&gt;Jordan Harrison&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

Photo by &lt;a href="https://unsplash.com/@aligns?utm_source=medium&amp;amp;utm_medium=referral"&gt;Jordan Harrison&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h4 id="idempotence-inhttp"&gt;Idempotence in HTTP&lt;/h4&gt;
&lt;p&gt;When talking about idempotence in the context of HTTP another term that pops up is safety, &lt;strong&gt;safety is where the request doesn’t mutate data on invocation&lt;/strong&gt;. The table below shows commonly used HTTP methods and there safety and idempotency.&lt;/p&gt;
&lt;p&gt;+&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;-+&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;ndash;+&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;-+&lt;br&gt;
| Http Method | Saftey | Idempotency |&lt;br&gt;
+&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;-+&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;ndash;+&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;-+&lt;br&gt;
| GET | Yes | Yes |&lt;br&gt;
| PUT | No | Yes |&lt;br&gt;
| POST | No | No |&lt;br&gt;
| DELETE | No | Yes |&lt;br&gt;
| PATCH | No | No |&lt;br&gt;
+&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;-+&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;ndash;+&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;-+&lt;/p&gt;
&lt;p&gt;Some methods are idempotent by the get-go. Take GET for an example, how many time you may call the GET method it results with the same outcome.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ℹ &lt;strong&gt;To be Idempotent only the action/intention is considered, the HTTP resdponse status code may differ, ie — The initial DELETE call may return 200, but the successive ones may return 404.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="why-is-idempotency-important-for-building-reliableapis"&gt;Why is Idempotency important for building reliable APIs?&lt;/h3&gt;
&lt;p&gt;Think of such a scenario; Networks are sometimes unreliable, In cases where an API consumer may send and request but because of a technical difficulty not receive the response. This may not be a problem for a GET request where it can be retried but is an issue for non-idempotent HTTP methods such as POST.&lt;/p&gt;
&lt;h4 id="introducing-the-idempotency-key"&gt;Introducing the idempotency key&lt;/h4&gt;
&lt;p&gt;With the prior given example let’s tackle the idempotency problem. To solve this problem we need an &lt;strong&gt;identifier to help denote whether the request is idempotent&lt;/strong&gt; which can be facilitated by an idempotency key.&lt;/p&gt;
&lt;p&gt;With an idempotency key, the server can know if the request is idempotent or not by keeping track of the keys sent by the client and treating a request idempotent if it comes with a previously used key.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-2"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/understanding-idempotency-in-rest-apis/1__GhDYXaU9DSNEHXtR0x7GmA_hu_c8fc08fa073352a6.webp" width="1000" height="790" class="summary-image" alt="Example Payment Scenario with Idempotency"&gt;
	
 &lt;figcaption&gt;Image 2: Example Payment Scenario with Idempotency&lt;/figcaption&gt;
&lt;/figure&gt;
Example Payment Scenario with Idempotency&lt;/p&gt;
&lt;p&gt;Given above is an example usage of a payment scenario where idempotency is used and is incorporated into the business logic.&lt;/p&gt;
&lt;h4 id="recommendations-for-implementing-idempotency-inapis"&gt;Recommendations for implementing idempotency in APIs&lt;/h4&gt;
&lt;p&gt;No defacto standard is offered and different implementers follow their own standards but the following points are kept constant.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use an HTTP header such as x-idempotency-key&lt;/li&gt;
&lt;li&gt;Invalidate idempotency keys after a pre-defined time period, therefore after the time period passes the request is treated as a new non-idempotent request.&lt;/li&gt;
&lt;li&gt;Validate bad behaving idempotency keys, In cases where the client may send a different payload for a certain key in the subsequent retries that may be treated as a new request or a bad request.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="api-consumer-considerations"&gt;API Consumer Considerations&lt;/h4&gt;
&lt;p&gt;A client application that is using an API implementing idempotency can follow the guidelines below to ensure proper usage.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Idempotency key can be any value, most recommend is the use of a UUID.&lt;/li&gt;
&lt;li&gt;Sending idempotent requests for polling status of objects should be avoided, as some APIs may allow that.&lt;/li&gt;
&lt;li&gt;When a request is unsuccessful better to follow a retry policy such as &lt;a href="https://en.wikipedia.org/wiki/Exponential_backoff"&gt;exponential backoff&lt;/a&gt;. This will ensure that in a scenario where the Server is amidst an incident that it’s not flooded with requests.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;**Resources Used&lt;br&gt;
**&lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Idempotent"&gt;https://developer.mozilla.org/en-US/docs/Glossary/Idempotent&lt;/a&gt;&lt;br&gt;
&lt;a href="https://stripe.com/en-US/blog/idempotency"&gt;https://stripe.com/en-US/blog/idempotency&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Introduction to Consumer Data Right Australia</title><link>https://ukr.lk/posts/introduction-to-consumer-data-right-australia/</link><pubDate>Sun, 31 Mar 2019 11:05:47 +0000</pubDate><guid>https://ukr.lk/posts/introduction-to-consumer-data-right-australia/</guid><description>&lt;p&gt;Consumer Data Right known as CDR for short has its roots with the &lt;a href="https://treasury.gov.au/node/3489"&gt;“Review into Open Banking in Australia”&lt;/a&gt; presented to the Australian government. After which the government decided to legislate the &lt;a href="https://www.accc.gov.au/focus-areas/consumer-data-right-cdr-0"&gt;Consumer Data Right&lt;/a&gt; late November 2017.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/introduction-to-consumer-data-right-australia/0__9MOROFAl9__72VDXM_hu_68b3c8bb38999558.webp" width="1000" height="669" class="summary-image" alt="Photo by Loïc Fürhoff on Unsplash"&gt;
	
 &lt;figcaption&gt;Image 1: Photo by &lt;a href="https://unsplash.com/@imagoiq?utm_source=medium&amp;amp;utm_medium=referral"&gt;Loïc Fürhoff&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

Photo by &lt;a href="https://unsplash.com/@imagoiq?utm_source=medium&amp;amp;utm_medium=referral"&gt;Loïc Fürhoff&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The Primary motive of CDR is to provide consumers the mechanism to obtain data from their service providers to allow comparing and to switch between service providers or products; increasing competition with service providers to yield better prices and provide innovative services or products.&lt;/p&gt;
&lt;p&gt;In short, the CDR will enable customers to share their data with competitors and other services with the consent of the customer.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The introduction of a consumer data right in Australia is a fundamental competition and consumer reform. The ACCC is delighted to lead the data right and to work in the best interest of consumers, — &lt;a href="https://www.accc.gov.au/media-release/accc-welcomes-consumer-data-right"&gt;Rod Sims ( ACCC Chairman)&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id="applications-of-consumer-dataright"&gt;Applications of Consumer Data Right&lt;/h4&gt;
&lt;p&gt;Consumer Data Right is not fixed to one sector. &lt;strong&gt;&lt;em&gt;The start would be Banking and will expand to energy and even telecommunication.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="understanding-consumer-dataright"&gt;Understanding Consumer Data Right&lt;/h3&gt;
&lt;p&gt;To understand consumer data right and it’s usage first we must look at the &lt;a href="https://www.accc.gov.au/focus-areas/consumer-data-right-cdr-0/rules-outline"&gt;&lt;strong&gt;key actors&lt;/strong&gt; involved&lt;/a&gt; in a CDR context.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-2"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/introduction-to-consumer-data-right-australia/1__PCtrkPqGAmHhkzZqsJIulA_hu_3a44bbd6db6668d9.webp" width="1000" height="285" class="summary-image" alt="Key Actors"&gt;
	
 &lt;figcaption&gt;Image 2: Key Actors&lt;/figcaption&gt;
&lt;/figure&gt;
Key Actors&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CDR Consumer&lt;/strong&gt; will be the end user who will be benefited from CDR, the consumer will be able to request the &lt;strong&gt;Data Holder&lt;/strong&gt; who is the organization which CDR will be applied to provide data to the consumer.&lt;/p&gt;
&lt;p&gt;A &lt;strong&gt;Data Recipient&lt;/strong&gt; is an accredited party that will be able to request CDR data from a Data Holder with the consent of the consumer. Data Recipients give s consumers a new perspective on their data and allow them to compare and gain better insights.&lt;/p&gt;
&lt;h4 id="what-data-will-be-offered-by-consumer-dataright"&gt;What data will be offered by Consumer Data Right?&lt;/h4&gt;
&lt;p&gt;The CDR enables the consumer to open up information to their person or another accredited data recipient with consent. The data mainly falls into two basic categories.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Information regarding themselves in a certain industry that is held by or held on behalf of the requested consumer.&lt;/li&gt;
&lt;li&gt;General information on the product/services by the provider, this data is not in any way relatable or identifiable to any certain consumer and will be available for all consumers or accredited data recipient.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="safeguards-set-in-place-for-the-best-interest-of-the-consumers"&gt;Safeguards set in place for the best interest of the consumers&lt;/h4&gt;
&lt;p&gt;The CDR is drafter with many safeguards in place for different scenarios, I’ll talk about some of the main safeguards put in place for the best interest of the consumer.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Data Holders should be equipped with the facility to allow the revocation of authorization consent, In the case where the consumer feels that a data holder doesn’t need access to the consumer&amp;rsquo;s data.&lt;/li&gt;
&lt;li&gt;Consent must be given in clear easy to understand language and accepted voluntarily by the consumer before data recipients are allowed to access CDR data.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Open banking Australia is the first to benefit from the CDR and is well on its the way with a &lt;a href="https://consumerdatastandardsaustralia.github.io/"&gt;regulatory draft specification&lt;/a&gt; released and is under active development under &lt;a href="https://www.data61.csiro.au/"&gt;Data61&lt;/a&gt; on an open collaboration model.&lt;/p&gt;</description></item><item><title>API Aggregators — The Success of PSD2</title><link>https://ukr.lk/posts/api-aggregators-the-success-of-psd2/</link><pubDate>Sat, 16 Mar 2019 09:05:31 +0000</pubDate><guid>https://ukr.lk/posts/api-aggregators-the-success-of-psd2/</guid><description>&lt;p&gt;With deadlines inching close for PSD2, Implementers are ready to open up sandbox environments for developers, kickstarting a new era of financial apps.&lt;/p&gt;
&lt;p&gt;This is great news, but as third parties are interested in onboarding with different specifications and banks, the involvement necessary is apparent.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/api-aggregators-the-success-of-psd2/0__QhszrwHbe5HLQ00u_hu_9dd30e05616e1b87.webp" width="1000" height="666" class="summary-image" alt="Photo by Tim Evans on Unsplash"&gt;
	
 &lt;figcaption&gt;Image 1: Photo by &lt;a href="https://unsplash.com/@tjevans?utm_source=medium&amp;amp;utm_medium=referral"&gt;Tim Evans&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

Photo by &lt;a href="https://unsplash.com/@tjevans?utm_source=medium&amp;amp;utm_medium=referral"&gt;Tim Evans&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;With Open Banking Specification groups hell-bent on increasing granularity of data offered and having up-most security is in the best interest of all stakeholders. With granularity and depth comes flexibility and freedom for a wide variety of opportunities, but hinders developer experience with after effects such as increased complexity.&lt;/p&gt;
&lt;p&gt;This is made worse with the fact that third parties need to be compliant with multiple specifications such as Open Banking UK, Berlin Group, STET, etc. As a third party’s best interest is to be on-boarded with many banks as possible.&lt;/p&gt;
&lt;p&gt;Complying to these specifications come with their own unique complexities.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Onboarding process for specification.&lt;/li&gt;
&lt;li&gt;Authentication flow.&lt;/li&gt;
&lt;li&gt;Data model and API resource mapping.&lt;/li&gt;
&lt;li&gt;Complying with customer experience guidelines enforced by specifications.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With the above-stated processes repeated for each specification, It becomes a paramount task.&lt;/p&gt;
&lt;h3 id="enter-api-aggregators"&gt;Enter API Aggregators&lt;/h3&gt;
&lt;p&gt;API Aggregators are in essence are a form of third part which exposes uniform abstracted financial APIs which allow interfacing with a wide variety of specifications and financial institutes with ease.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;img src="https://ukr.lk/posts/api-aggregators-the-success-of-psd2/1__kqkDmfS04__5fJ7Ble1vHIg.png"&gt;
&lt;/figure&gt;

Shown above are two example scenarios, one where the third part directly integrates with the bank, denoted by &lt;strong&gt;“1”&lt;/strong&gt; and an API aggregation scenario where third parties are on-boarded with the aggregator, denoted by &lt;strong&gt;“2”.&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Third Party onboard with the bank implementing specification A. Extra effort is now needed to support Specification B and to enroll with the other two banks.&lt;/li&gt;
&lt;li&gt;Third Parties are enrolled with the API aggregator and instantly support specification A and B and all of the banks enrolled with the aggregator.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;With the above illustration, it’s clear why a third party will opt-in for an API aggregator to ease the integration process and to support many banks as possible.&lt;/p&gt;
&lt;h4 id="how-api-aggregators-play-a-key-role-in-openbanking"&gt;How API Aggregators play a key role in Open Banking&lt;/h4&gt;
&lt;p&gt;In summary API Aggregators will be the enabler of PSD2, allowing third parties to scale throughout the EU and even beyond. Given below are some key points stating the benefits for different stakeholders.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For Banks&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Small scale banks with a little foothold on the market will be not left behind as third parties are more interested in complying with the major players.&lt;/li&gt;
&lt;li&gt;More third-party application traffic with API Aggregator adoption.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;For Third Parties&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Instant access to many banks and specifications.&lt;/li&gt;
&lt;li&gt;Not necessary to keep track of specifications for updates and depreciation of API’s.&lt;/li&gt;
&lt;li&gt;Not necessary to track API depreciation or updates.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now It’s clear how API Aggregators will play an important part of PSD2 and bring it to masses. Making the developer experience smoother and also truly leveling the playfield with third parties and banks.&lt;/p&gt;</description></item><item><title>Implementing Detached JSON Web Signature</title><link>https://ukr.lk/posts/implementing-detached-json-web-signature-9ca5665ddcfc/</link><pubDate>Sun, 03 Feb 2019 11:23:31 +0000</pubDate><guid>https://ukr.lk/posts/implementing-detached-json-web-signature-9ca5665ddcfc/</guid><description>&lt;p&gt;In some cases where you’re required to integrity protect content that is already existing and not contained in a JWS, It’s possible by attaching a JWS signature without a payload as an external attribute according to &lt;a href="https://tools.ietf.org/html/rfc7515#appendix-F"&gt;RFC7515 — Appendix F&lt;/a&gt; for JWS integrity protection, this method is known as the Detached Content approach.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/implementing-detached-json-web-signature-9ca5665ddcfc/0__g__ACElnzaaThE7ly_hu_c1705de25216628f.webp" width="1000" height="563" class="summary-image" alt="Photo by Mike Kononov on Unsplash"&gt;
	
 &lt;figcaption&gt;Image 1: Photo by &lt;a href="https://unsplash.com/@mikofilm?utm_source=medium&amp;amp;utm_medium=referral"&gt;Mike Kononov&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

Photo by &lt;a href="https://unsplash.com/@mikofilm?utm_source=medium&amp;amp;utm_medium=referral"&gt;Mike Kononov&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="decomposition-of-a-standardjws"&gt;Decomposition of a standard JWS&lt;/h3&gt;
&lt;p&gt;We’ll first take a look at a standard JWS which will allow us to understand the implement the detached approach as the fundamental lies here. A JWS is a string composed of three components separated by ‘.’&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;base64UrlEncode(Header) + ‘.’ + base64UrlEncode(Payload) + ‘.’ + base64UrlEncode(JSONWebSignature)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The header contains information such as the algorithm used and the payload is the value that requires integrity protection. The JSON web signature is simply the first two parts hashed with a secret thus allowing any other party to validate the payload’s authenticity by using a public key.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;JSONWebSignature&lt;/strong&gt; = RSASHA256( base64UrlEncode(&lt;strong&gt;header&lt;/strong&gt;) + “.” +base64UrlEncode(&lt;strong&gt;payload&lt;/strong&gt;), &lt;strong&gt;secret&lt;/strong&gt;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="detached-approach"&gt;Detached Approach&lt;/h3&gt;
&lt;p&gt;The fundamentals of encoding and decoding JWS still remains in this approach with the exception where the payload is redacted from the JWS and sent separately.&lt;/p&gt;
&lt;h4 id="example-usecase"&gt;Example use case&lt;/h4&gt;
&lt;p&gt;One option would be to use in REST APIs as it provides an easy way of ensuring integrity. The signature can be sent over in the request or response as a header, such as&lt;code&gt;x-jws-signature&lt;/code&gt;which the client or server can validate the HTTP payload using the signature.&lt;/p&gt;
&lt;h4 id="implementing-the-detachedapproach"&gt;Implementing the detached approach&lt;/h4&gt;
&lt;p&gt;This is fairly simple as you’re able to use your standard JWS libraries to perform this task and then by manipulating the input/output, you’ll be able to extract the detached JWS. Given below are example implementations in Python using pyjwt.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Encoding&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create standard JWS with the header and payload&lt;/li&gt;
&lt;li&gt;Split the JWS output by ‘.’&lt;/li&gt;
&lt;li&gt;Replace the second element with an empty string ‘’ thus removing the payload.&lt;/li&gt;
&lt;li&gt;Join the JWS back together with ‘.’&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Decoding&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In the decoding process, the previously mentioned encoding process is to be reversed. Making sure to base64 URL encode the payload, this recreates the JWS.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Split JWS by ‘.’&lt;/li&gt;
&lt;li&gt;Replace the second element with the payload encoded using Base64 URL.&lt;/li&gt;
&lt;li&gt;Rejoin the modified JWS with ‘.’&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;As you can see this can be implemented quite easily by manipulating inputs and outputs of existing JWS implementations. This is a great option for introducing non-intrusive integrity validation for existing mediums.&lt;/p&gt;</description></item><item><title>Better UX for PSD2 Strong Customer Authentication using Transaction Risk Analysis</title><link>https://ukr.lk/posts/better-ux-for-psd2-strong-customer-authentication-using-transaction-risk-analysis/</link><pubDate>Sun, 27 Jan 2019 18:07:37 +0000</pubDate><guid>https://ukr.lk/posts/better-ux-for-psd2-strong-customer-authentication-using-transaction-risk-analysis/</guid><description>&lt;p&gt;One of the main highlights of PSD2 is Its keen eye on customer authentication, PSD2 mandates strong customer authentication[1] known as SCA in short. Even though It’s important to keep SCA on the driver&amp;rsquo;s seat, With an increased number of transactions by users it can quickly become a burden.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/better-ux-for-psd2-strong-customer-authentication-using-transaction-risk-analysis/0__GohHahZg1EsfXoKr_hu_53467d01654abaeb.webp" width="1000" height="653" class="summary-image" alt="Photo by CMDR Shane on Unsplash"&gt;
	
 &lt;figcaption&gt;Image 1: Photo by &lt;a href="https://unsplash.com/@cmdrshane?utm_source=medium&amp;amp;utm_medium=referral"&gt;CMDR Shane&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

Photo by &lt;a href="https://unsplash.com/@cmdrshane?utm_source=medium&amp;amp;utm_medium=referral"&gt;CMDR Shane&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="strong-customer-authentication"&gt;Strong Customer Authentication&lt;/h3&gt;
&lt;p&gt;Strong customer authentication as defined by PSD2 is based on two or more factors of authentication. These factors are categorized into three main groups, Knowledge, Possession and inheritance[2].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;‘strong customer authentication’ means an authentication based on the use of two or more elements categorised as knowledge (something only the user knows), possession (something only the user possesses) and inherence (something the user is) — PSD2&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;

&lt;figure id="image-2"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/better-ux-for-psd2-strong-customer-authentication-using-transaction-risk-analysis/1__xFmJK7FkTV9iA2RLY3hRCQ_hu_99c9977dc33165d9.webp" width="1000" height="513" class="summary-image" alt="Icons made by Smashicons / Pixel perfect from www.flaticon.com is licensed by CC 3.0 BY"&gt;
	
 &lt;figcaption&gt;Image 2: Icons made by &lt;a href="https://smashicons.com/" title="Smashicons"&gt;Smashicons&lt;/a&gt; / &lt;a href="https://icon54.com/" title="Pixel perfect"&gt;Pixel perfect&lt;/a&gt; from &lt;a href="https://www.flaticon.com/" title="Flaticon"&gt;www.flaticon.com&lt;/a&gt; is licensed by &lt;a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0"&gt;CC 3.0 BY&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

Icons made by &lt;a href="https://smashicons.com/" title="Smashicons"&gt;Smashicons&lt;/a&gt; / &lt;a href="https://icon54.com/" title="Pixel perfect"&gt;Pixel perfect&lt;/a&gt; from &lt;a href="https://www.flaticon.com/" title="Flaticon"&gt;www.flaticon.com&lt;/a&gt; is licensed by &lt;a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0"&gt;CC 3.0 BY&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The infographic above shows categories defined by PSD2 for strong customer authentication. In an example for Open Banking, a bank can opt into using user-name, password credentials(Knowledge) as the primary method and SMS one-time password(Possession) as the secondary factor.&lt;/p&gt;
&lt;h4 id="user-experience-issues-caused-bysca"&gt;User experience issues caused by SCA&lt;/h4&gt;
&lt;p&gt;With PSD2 mandating SCA in cases where a PSU (Payment Services User) may be heavily consuming open banking resources, SCA protected information will be presented with multi-factor authentication regardless of the action. As it’s now apparent how this can be a huge burden on the PSU.&lt;/p&gt;
&lt;h3 id="transaction-riskanalysis"&gt;Transaction Risk Analysis&lt;/h3&gt;
&lt;p&gt;Even though PSD2 has mandated SCA, it can be exempted using transaction risk analysis known in short as TRA. TRA is a contextual system where applying of SCA is determined by the risk of the transaction. Rules for TRA are defined in the regulatory standards document[3] for implementers to follow.&lt;/p&gt;
&lt;p&gt;For example, in the case of a low-value transaction, SCA is exempted thus allowing the PSU to swiftly authorize. Thus increasing UX while not compromising on security.&lt;/p&gt;
&lt;p&gt;**References&lt;br&gt;
**[1] &lt;a href="https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:32015L2366&amp;amp;from=EN"&gt;PSD2&lt;/a&gt; — Article 97(1)&lt;br&gt;
[2] &lt;a href="https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:32015L2366&amp;amp;from=EN"&gt;PSD2 &lt;/a&gt;— Article 4(30)&lt;br&gt;
[3] &lt;a href="https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:32018R0389&amp;amp;from=EN"&gt;RTS&lt;/a&gt; — Article 18&lt;/p&gt;</description></item><item><title>Open Banking and PSD2 simplified.</title><link>https://ukr.lk/posts/open-banking-and-psd2-simplified/</link><pubDate>Tue, 15 Jan 2019 15:19:13 +0000</pubDate><guid>https://ukr.lk/posts/open-banking-and-psd2-simplified/</guid><description>&lt;p&gt;The wave of Open Banking has hit the shore, is it a fad or a goldmine? only time will decide, I believe in the latter. It is no secret, Open banking related buzzwords have been floating on the web and some readers are left utterly confused and others misinformed with thoughts such as “my data will be exposed to other parties”, which is hardly from the truth.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/open-banking-and-psd2-simplified/0__ExHYIQISjFJ__HpUd_hu_5951f555fab80991.webp" width="1000" height="666" class="summary-image" alt="Photo by Sean Pollock on Unsplash"&gt;
	
 &lt;figcaption&gt;Image 1: Photo by &lt;a href="https://unsplash.com/@seanpollock?utm_source=medium&amp;amp;utm_medium=referral"&gt;Sean Pollock&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

Photo by &lt;a href="https://unsplash.com/@seanpollock?utm_source=medium&amp;amp;utm_medium=referral"&gt;Sean Pollock&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The inception of open banking is directly tied in with PSD2 directive which was bought to public attention in late November 2015.&lt;/p&gt;
&lt;h3 id="payments-service-directive"&gt;Payments Service Directive&lt;/h3&gt;
&lt;p&gt;It all started with PSD2, Payments Service Directive 2 is a European Union Directive that regulates payment services and it’s providers. PSD2’s goals were set on increasing pan-European competition and participation in the payments sector, not only limited to banks.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The directive establishes a clear and comprehensive set of rules that will apply to existing and new providers of innovative payment services. These rules seek to ensure that these players can compete on equal terms, leading to greater efficiency, choice and transparency of payment services, while strengthening consumers’ trust in a harmonised payments market. — PSD2 &lt;a href="https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=LEGISSUM:2404020302_1&amp;amp;from=EN"&gt;Summary&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="open-banking"&gt;Open Banking&lt;/h3&gt;
&lt;p&gt;Inspired by OpenData and with PSD2 as the backbone, Open Banking was born. Open Banking is essentially an API (Application Programming Interface) that allows external regulated third parties to interact with banks in a unified fashion.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;API — Set of functions and procedures that allow different systems to communicate&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id="how-it-was-before-openbanking"&gt;How it was before Open Banking?&lt;/h4&gt;
&lt;p&gt;Payment services and banking was monopolized, consumers were locked into the ecosystem that individual banks provided. As for the involvement of third parties for payment services was limited therefore consumers were interacting with banks independently with the services provided.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-2"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/open-banking-and-psd2-simplified/1__bEBMJQh46iAD9lnRJAO5Yw_hu_54d759a065193e67.webp" width="1000" height="613" class="summary-image" alt="Icons made by Pixel perfect from www.flaticon.com is licensed by CC 3.0 BY"&gt;
	
 &lt;figcaption&gt;Image 2: Icons made by &lt;a href="https://icon54.com/" title="Pixel perfect"&gt;Pixel perfect&lt;/a&gt; from &lt;a href="https://www.flaticon.com/" title="Flaticon"&gt;www.flaticon.com&lt;/a&gt; is licensed by &lt;a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0"&gt;CC 3.0 BY&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

Icons made by &lt;a href="https://icon54.com/" title="Pixel perfect"&gt;Pixel perfect&lt;/a&gt; from &lt;a href="https://www.flaticon.com/" title="Flaticon"&gt;www.flaticon.com&lt;/a&gt; is licensed by &lt;a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0"&gt;CC 3.0 BY&lt;/a&gt;&lt;/p&gt;
&lt;h4 id="what-open-banking-enables-thirdparties"&gt;What Open Banking enables third parties?&lt;/h4&gt;
&lt;p&gt;Open banking exposes financial services to third parties, these can be consumed by third parties to create applications or services for consumers.&lt;/p&gt;
&lt;p&gt;This enables a new industry of applications that integrate with Open Banking APIs to give a new experience for consumers to provide insight into their financial data and allow easy payments.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-3"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/open-banking-and-psd2-simplified/1__tS__o29GgkgtHei__EgbRUGg_hu_82dbc5a556123630.webp" width="1000" height="719" class="summary-image" alt="Icons made by Pixel perfect from www.flaticon.com is licensed by CC 3.0 BY"&gt;
	
 &lt;figcaption&gt;Image 3: Icons made by &lt;a href="https://icon54.com/" title="Pixel perfect"&gt;Pixel perfect&lt;/a&gt; from &lt;a href="https://www.flaticon.com/" title="Flaticon"&gt;www.flaticon.com&lt;/a&gt; is licensed by &lt;a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0"&gt;CC 3.0 BY&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

Icons made by &lt;a href="https://icon54.com/" title="Pixel perfect"&gt;Pixel perfect&lt;/a&gt; from &lt;a href="https://www.flaticon.com/" title="Flaticon"&gt;www.flaticon.com&lt;/a&gt; is licensed by &lt;a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0"&gt;CC 3.0 BY&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Services provided in Open Banking can be categorized into two.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Account information services&lt;/strong&gt; which expose account and transactional information for gaining better knowledge on a consumer’s financial status.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Payment initiation services&lt;/strong&gt; which allow consumers to pay via credit transfers allowing goods to be released with a minimum delay.&lt;/p&gt;
&lt;h4 id="security-andconsent"&gt;Security and Consent&lt;/h4&gt;
&lt;p&gt;Open Banking is designed with security and consent in mind. By design, the third party providers are not able to retrieve transactions or submit payments without explicit consent from the consumer.&lt;/p&gt;
&lt;p&gt;An example procedure is shown below. On initiation of a third party application, the third party will request consent for the transaction and the bank will confirm it with the consumer after which the transaction will take place.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-4"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/open-banking-and-psd2-simplified/1__DWZW8shjY1LfOyEqFie9CA_hu_d277871cc8aa0a23.webp" width="1000" height="773" class="summary-image" alt="Icons made by Pixel perfect from www.flaticon.com is licensed by CC 3.0 BY"&gt;
	
 &lt;figcaption&gt;Image 4: Icons made by &lt;a href="https://icon54.com/" title="Pixel perfect"&gt;Pixel perfect&lt;/a&gt; from &lt;a href="https://www.flaticon.com/" title="Flaticon"&gt;www.flaticon.com&lt;/a&gt; is licensed by &lt;a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0"&gt;CC 3.0 BY&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

Icons made by &lt;a href="https://icon54.com/" title="Pixel perfect"&gt;Pixel perfect&lt;/a&gt; from &lt;a href="https://www.flaticon.com/" title="Flaticon"&gt;www.flaticon.com&lt;/a&gt; is licensed by &lt;a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0"&gt;CC 3.0 BY&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Most Open Banking APIs are designed with open source methodologies where groups of people over the internet collaborate to provide ideas to make it secure as possible.&lt;/p&gt;</description></item><item><title>Generating JAX-RS APIs from Swagger definitions</title><link>https://ukr.lk/posts/generating-jax-rs-apis-from-swagger-definitions/</link><pubDate>Sun, 13 Jan 2019 04:36:29 +0000</pubDate><guid>https://ukr.lk/posts/generating-jax-rs-apis-from-swagger-definitions/</guid><description>&lt;blockquote&gt;
&lt;p&gt;The sample project is available on &lt;a href="https://github.com/kaveenr/jaxrs-swagger-codegen-sample"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;With the virtues of OpenAPI specifications, it’s a waste of human resources to create API services by hand. Despite that thought what shocked me the most was the lack of documentation from Swagger end on their code-generation plugin. As the generation tool is fully featured and constantly updated but documentation is sparse regarding the availability of JAX-RS as an option.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/generating-jax-rs-apis-from-swagger-definitions/0__ScEjlUymnCTqKil___hu_dc3bf7ec16ae0fbe.webp" width="1000" height="666" class="summary-image" alt="Photo by Harry Cunningham on Unsplash"&gt;
	
 &lt;figcaption&gt;Image 1: Photo by &lt;a href="https://unsplash.com/@harrycunnningham1?utm_source=medium&amp;amp;utm_medium=referral"&gt;Harry Cunningham&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

Photo by &lt;a href="https://unsplash.com/@harrycunnningham1?utm_source=medium&amp;amp;utm_medium=referral"&gt;Harry Cunningham&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This guide will explore how the &lt;a href="https://github.com/swagger-api/swagger-codegen/tree/master/modules/swagger-codegen-maven-plugin"&gt;&lt;strong&gt;swagger-codegen-maven-plugin&lt;/strong&gt;&lt;/a&gt; can be used to generate API interfaces in Java with Maven.&lt;/p&gt;
&lt;h4 id="maven-configuration"&gt;Maven Configuration&lt;/h4&gt;
&lt;p&gt;The plugin is configurable as maven goal, where you are able to define the generation source folder and also packages for the generated artifacts.&lt;/p&gt;
&lt;p&gt;I’ve opted to use generic Response as It’s much more intuitive and clean to do so instead of the default model return type which is specified in this &lt;strong&gt;&lt;configOptions&gt;&lt;/strong&gt; section&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The generation process can be invoked with &lt;strong&gt;‘mvn clean instal’&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;and if you don’t fancy the generation process being re-triggered on each run after the initial invocation &lt;strong&gt;&lt;skip&gt;true&lt;/skip&gt;&lt;/strong&gt; can be set in place.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id="api-implementation"&gt;API Implementation&lt;/h4&gt;
&lt;p&gt;The maven specified invokerPackage will contain the generated API template ready to be implemented. Now we can go ahead and implement the given templates.&lt;/p&gt;
&lt;p&gt;Afterward, we need to add the service bean to beans.xml and voila we’re done.&lt;/p&gt;
&lt;p&gt;What’s remaining is to compile the project and test it out, I added Docker compose to quickly start up an instance of tomcat to do so.&lt;/p&gt;</description></item><item><title>Wax Records and Parent Teacher Meetings</title><link>https://ukr.lk/posts/wax-records-and-parent-teacher-meetings/</link><pubDate>Mon, 01 Oct 2018 01:29:11 +0000</pubDate><guid>https://ukr.lk/posts/wax-records-and-parent-teacher-meetings/</guid><description>&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/wax-records-and-parent-teacher-meetings/1__sRwJvnt8__Poam34hu__u7Ng_hu_c46ad37a5c6efc58.webp" width="1000" height="688" class="summary-image" alt="This story is brought to you by the smell of old Vinyl records I was digging at Vinyl Revival"&gt;
	
 &lt;figcaption&gt;Image 1: This story is brought to you by the smell of old Vinyl records I was digging at Vinyl Revival&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;It’s 10am, many disappointing conversations with teachers later. Let’s say I was uninspired but honestly I can’t imagine what was up with me back then. Flunking all my exams and being in the bottom of my class. One saving grace of those dreaded parent teacher meeting days is getting to leave early from school.&lt;/p&gt;
&lt;p&gt;My dad didn’t say much regarding my exams, both my parents knew I was going to be some computer wizard, How? Why? Your guess is as good as mine. We take the 100 bus up to Bambalapitiya to look at records.&lt;/p&gt;
&lt;p&gt;He didn’t have to take me home early I could have taken my school van, I guess it’s my dad’s way of telling me.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“I don’t care about your marks, let’s just buy some music.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;

&lt;figure id="image-2"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/wax-records-and-parent-teacher-meetings/1__Js2rNU__WZiqG0ItjjkRlHQ_hu_321d423227a5d00e.webp" width="1000" height="644" class="summary-image" alt="Photographer : Unknown"&gt;
	
 &lt;figcaption&gt;Image 2: Photographer : Unknown&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;The name was U.G. Danny, he had a small street side shop with an assortment of records from the late 60’s to the popist 80’s synthpop which my dad enjoyed. My dad has been collecting newspaper clippings from the UK top 40 since the 80’s and knows his pop, I had to grow up with that.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;My dad sold his record collection many years ago when the money was tough, and gave into digital audio.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-3"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/wax-records-and-parent-teacher-meetings/1__GB2SPn6RRRwr2ber7RToEQ_hu_bff8b81afdf50a04.webp" width="1000" height="750" class="summary-image" alt="25the December 2016"&gt;
	
 &lt;figcaption&gt;Image 3: 25the December 2016&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Two years ago I bought my dad a record player for Christmas, It was magical the first night we bought it home and played some 45’s we had left. Hearing Alphaville’s forever young again on the turntable was nostalgic reminding me of the older days. My father wasn’t ready to get back into Vinyl, He said that he had left that in the past and he’s happy with his CD collection.&lt;/p&gt;
&lt;p&gt;With my re-gifted Vinyl player he gave me a a pair of Kenwood LSK-333 speakers, I bought an amplifier and fell in love with the format.&lt;/p&gt;
&lt;p&gt;It seems after all those disappointing parent teacher meetings I’ve become that computer wizard my parents thought and now I spend my hard earned cash for the love of music.&lt;/p&gt;</description></item><item><title>Recreating the THX Deep Note in JavaScript</title><link>https://ukr.lk/posts/recreating-the-thx-deep-note-in-javascript/</link><pubDate>Sat, 26 May 2018 20:56:36 +0000</pubDate><guid>https://ukr.lk/posts/recreating-the-thx-deep-note-in-javascript/</guid><description>&lt;p&gt;THX celebrates their 35th anniversary somewhere in this week. Short bit of history THX’s inception in 1983 was to make sure that the soundtrack of StarWars Return Of The Jedi be reproduced and heard the way it should be apart from being scared the shit out in theaters.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/James_A._Moorer"&gt;Dr. James A. Moorer&lt;/a&gt; former employee of Lucas films computer division was tasked with creating the sound for THX. Which now is one of the most iconic sounds that the masses associate THX with. Not just a sound, the sound it self has become a pop culture icon, IE- the famous Simpsons skit.&lt;/p&gt;
&lt;h3 id="recreation-time"&gt;Recreation time&lt;/h3&gt;
&lt;p&gt;Enough yapping around, Let’s get to specs on creating the Deep Note. United States Patent and Trademark Office to the rescue as the &lt;a href="http://tsdr.uspto.gov/#caseNumber=74309951&amp;amp;caseType=SERIAL_NO&amp;amp;searchType=statusSearch"&gt;trademark document&lt;/a&gt; contains basic details on the sound but not the note itself.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The THX logo theme consists of 30 voices over seven measures, starting in a narrow range, 200 to 400 Hz, and slowly diverting to preselected pitches encompassing three octaves. The 30 voices begin at pitches between 200 Hz and 400 Hz and arrive at pre-selected pitches spanning three octaves by the fourth measure. The highest pitch is slightly detuned while there are double the number of voices of the lowest two pitches.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;“preselected pitches” eh? Today &lt;a href="https://twitter.com/THX/status/1000077588415447040"&gt;THX Offical Twitter&lt;/a&gt; put out a tweet with the score of the piece. I know one can easily do a spectrogram and on the note and determine the pitches, but this image inspired me to recreate the sound with the details give in the score.&lt;/p&gt;
&lt;p&gt;

&lt;figure id="image-1"&gt;
	
		
		&lt;img src="https://ukr.lk/posts/recreating-the-thx-deep-note-in-javascript/1__oa8axtHOdZhdz76NO73nOA_hu_97032cbb23fd56e6.webp" width="1000" height="563" class="summary-image" alt="THX Deep Note Score"&gt;
	
 &lt;figcaption&gt;Image 1: THX Deep Note Score&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;That’s much clear, I’m terrible at reading sheet music but this seemed fairly simple. With the aid of &lt;a href="https://tonejs.github.io/"&gt;Tone.js&lt;/a&gt; I was easily able to recreate the Deep Note in JavaScript. though it sound like the chord is off but the general feel of it is there.&lt;/p&gt;
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/tone/13.1.20/Tone.min.js"&gt;&lt;/script&gt;
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"&gt;&lt;/script&gt;
&lt;script src="app.js"&gt;&lt;/script&gt;
&lt;details&gt;
 &lt;summary&gt;THX Demo&lt;/summary&gt;
 &lt;p&gt;Please lower your volume, before clicking the button&lt;/p&gt;
 &lt;button id="start"&gt;THX Button&lt;/button&gt;
&lt;/details&gt;
&lt;p&gt;Well that turned out okay, the code is a bit hacky and messy but gets the job done. Need to fix those pitches tho.&lt;/p&gt;
&lt;h3 id="source-code"&gt;Source Code&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;filter&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Tone&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Filter&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;150&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;lowpass&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mixer&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Tone&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Volume&lt;/span&gt;(&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;250&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;chain&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;filter&lt;/span&gt;,&lt;span style="color:#a6e22e"&gt;Tone&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Master&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;THXOsc&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;constructor&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;pitch&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;n&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;vol&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;osc&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;freq&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;pitch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;drift&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Tone&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;CtrlRandom&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;200&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;400&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;n&lt;/span&gt;; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;&lt;span style="color:#f92672"&gt;++&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;start_frq&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;drift&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;o&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Tone&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Oscillator&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;start_frq&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;sawtooth32&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;o&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;detune&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (Math.&lt;span style="color:#a6e22e"&gt;random&lt;/span&gt;() &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;) &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;o&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;volume&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;vol&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;osc&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;push&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;o&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;makeRamp&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;osc&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;osc&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;frequency&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;linearRampTo&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;drift&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;osc&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;frequency&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;linearRampTo&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;drift&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;osc&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;frequency&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;linearRampTo&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;freq&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;start&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;osc&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;osc&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;makeRamp&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;osc&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;pan&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Tone&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Panner&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Tone&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;CtrlRandom&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;osc&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;chain&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;pan&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;mixer&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;start&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;stop&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;osc&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;osc&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;osc&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;stop&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;OSC_POOL&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;TARGET_THREE&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#34;A3&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;D3&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;A4&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;D4&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;A5&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;D5&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;A5&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;F#5&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;TARGET_TWO&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#34;A1&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;D1&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;D0&amp;#34;&lt;/span&gt;]; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;generatePitches&lt;/span&gt;(){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;OSC_POOL&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;OSC_POOL&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;OSC_POOL&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;concat&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;TARGET_THREE&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;map&lt;/span&gt;((&lt;span style="color:#a6e22e"&gt;str&lt;/span&gt;) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;THXOsc&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;Tone&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Frequency&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;str&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;toFrequency&lt;/span&gt;(), &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;OSC_POOL&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;OSC_POOL&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;concat&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;TARGET_TWO&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;map&lt;/span&gt;((&lt;span style="color:#a6e22e"&gt;str&lt;/span&gt;) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;THXOsc&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;Tone&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Frequency&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;str&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;toFrequency&lt;/span&gt;(), &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;startSound&lt;/span&gt;(){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;mixer&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;volume&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;filter&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;frequency&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;150&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;osc&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;OSC_POOL&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;osc&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;start&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;mixer&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;volume&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;linearRampTo&lt;/span&gt;(&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;filter&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;frequency&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;linearRampToValueAtTime&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Tone&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Frequency&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;A8&amp;#34;&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;toFrequency&lt;/span&gt;(),&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; );
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;mixer&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;volume&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;linearRampTo&lt;/span&gt;(&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;stopSound&lt;/span&gt;(){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;mixer&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;volume&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;osc&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;OSC_POOL&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;osc&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;stop&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;$&lt;/span&gt;(document).&lt;span style="color:#a6e22e"&gt;ready&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;$&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;#start&amp;#39;&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;click&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;(){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;stopSound&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;generatePitches&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;startSound&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item></channel></rss>